dspy 0.34.2 → 0.34.3
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 +4 -4
- data/lib/dspy/chain_of_thought.rb +3 -2
- data/lib/dspy/context.rb +17 -1
- data/lib/dspy/evals/version.rb +1 -1
- data/lib/dspy/evals.rb +42 -31
- data/lib/dspy/events.rb +2 -3
- data/lib/dspy/example.rb +1 -1
- data/lib/dspy/lm/adapter.rb +39 -0
- data/lib/dspy/lm/json_strategy.rb +37 -2
- data/lib/dspy/lm/message.rb +1 -1
- data/lib/dspy/lm/response.rb +1 -1
- data/lib/dspy/lm/usage.rb +4 -4
- data/lib/dspy/lm.rb +9 -49
- data/lib/dspy/mixins/type_coercion.rb +189 -30
- data/lib/dspy/module.rb +70 -25
- data/lib/dspy/predict.rb +32 -5
- data/lib/dspy/prediction.rb +15 -57
- data/lib/dspy/prompt.rb +50 -30
- data/lib/dspy/propose/dataset_summary_generator.rb +1 -1
- data/lib/dspy/propose/grounded_proposer.rb +3 -3
- data/lib/dspy/re_act.rb +0 -162
- data/lib/dspy/registry/signature_registry.rb +3 -3
- data/lib/dspy/ruby_llm/lm/adapters/ruby_llm_adapter.rb +1 -27
- data/lib/dspy/schema/sorbet_json_schema.rb +7 -6
- data/lib/dspy/schema/version.rb +1 -1
- data/lib/dspy/schema_adapters.rb +1 -1
- data/lib/dspy/storage/program_storage.rb +2 -2
- data/lib/dspy/structured_outputs_prompt.rb +3 -3
- data/lib/dspy/teleprompt/utils.rb +2 -2
- data/lib/dspy/tools/github_cli_toolset.rb +7 -7
- data/lib/dspy/tools/text_processing_toolset.rb +2 -2
- data/lib/dspy/tools/toolset.rb +1 -1
- data/lib/dspy/version.rb +1 -1
- data/lib/dspy.rb +1 -4
- metadata +1 -26
- data/lib/dspy/events/subscriber_mixin.rb +0 -79
- data/lib/dspy/events/subscribers.rb +0 -43
- data/lib/dspy/memory/embedding_engine.rb +0 -68
- data/lib/dspy/memory/in_memory_store.rb +0 -216
- data/lib/dspy/memory/local_embedding_engine.rb +0 -244
- data/lib/dspy/memory/memory_compactor.rb +0 -298
- data/lib/dspy/memory/memory_manager.rb +0 -266
- data/lib/dspy/memory/memory_record.rb +0 -163
- data/lib/dspy/memory/memory_store.rb +0 -90
- data/lib/dspy/memory.rb +0 -30
- data/lib/dspy/tools/memory_toolset.rb +0 -117
data/lib/dspy/prompt.rb
CHANGED
|
@@ -26,24 +26,14 @@ module DSPy
|
|
|
26
26
|
sig { returns(T.nilable(String)) }
|
|
27
27
|
attr_reader :signature_class_name
|
|
28
28
|
|
|
29
|
-
# Returns the effective schema format
|
|
30
|
-
# Precedence: instance variable (if not :json default) > config.lm > :json
|
|
31
29
|
sig { returns(Symbol) }
|
|
32
30
|
def schema_format
|
|
33
|
-
|
|
34
|
-
return @schema_format if @schema_format && @schema_format != :json
|
|
35
|
-
|
|
36
|
-
# Otherwise, read from config if available
|
|
37
|
-
DSPy.config.lm&.schema_format || @schema_format || :json
|
|
31
|
+
@schema_format || :json
|
|
38
32
|
end
|
|
39
33
|
|
|
40
34
|
sig { returns(Symbol) }
|
|
41
35
|
def data_format
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
lm = DSPy.config.lm
|
|
45
|
-
lm_format = lm&.respond_to?(:data_format) ? lm.data_format : nil
|
|
46
|
-
lm_format || @data_format || :json
|
|
36
|
+
@data_format || :json
|
|
47
37
|
end
|
|
48
38
|
|
|
49
39
|
sig { returns(T.nilable(T.class_of(Signature))) }
|
|
@@ -56,20 +46,20 @@ module DSPy
|
|
|
56
46
|
output_schema: T::Hash[Symbol, T.untyped],
|
|
57
47
|
few_shot_examples: T::Array[FewShotExample],
|
|
58
48
|
signature_class_name: T.nilable(String),
|
|
59
|
-
schema_format: Symbol,
|
|
49
|
+
schema_format: T.nilable(Symbol),
|
|
60
50
|
signature_class: T.nilable(T.class_of(Signature)),
|
|
61
|
-
data_format: Symbol
|
|
51
|
+
data_format: T.nilable(Symbol)
|
|
62
52
|
).void
|
|
63
53
|
end
|
|
64
|
-
def initialize(instruction:, input_schema:, output_schema:, few_shot_examples: [], signature_class_name: nil, schema_format:
|
|
54
|
+
def initialize(instruction:, input_schema:, output_schema:, few_shot_examples: [], signature_class_name: nil, schema_format: nil, signature_class: nil, data_format: nil)
|
|
65
55
|
@instruction = instruction
|
|
66
56
|
@few_shot_examples = few_shot_examples.freeze
|
|
67
57
|
@input_schema = input_schema.freeze
|
|
68
58
|
@output_schema = output_schema.freeze
|
|
69
59
|
@signature_class_name = signature_class_name
|
|
70
|
-
@schema_format = schema_format
|
|
60
|
+
@schema_format = resolve_schema_format(schema_format)
|
|
71
61
|
@signature_class = signature_class
|
|
72
|
-
@data_format = data_format
|
|
62
|
+
@data_format = resolve_data_format(data_format)
|
|
73
63
|
end
|
|
74
64
|
|
|
75
65
|
# Immutable update methods for optimization
|
|
@@ -107,6 +97,34 @@ module DSPy
|
|
|
107
97
|
with_examples(combined_examples)
|
|
108
98
|
end
|
|
109
99
|
|
|
100
|
+
sig { params(new_schema_format: Symbol).returns(Prompt) }
|
|
101
|
+
def with_schema_format(new_schema_format)
|
|
102
|
+
self.class.new(
|
|
103
|
+
instruction: @instruction,
|
|
104
|
+
input_schema: @input_schema,
|
|
105
|
+
output_schema: @output_schema,
|
|
106
|
+
few_shot_examples: @few_shot_examples,
|
|
107
|
+
signature_class_name: @signature_class_name,
|
|
108
|
+
schema_format: new_schema_format,
|
|
109
|
+
signature_class: @signature_class,
|
|
110
|
+
data_format: @data_format
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
sig { params(new_data_format: Symbol).returns(Prompt) }
|
|
115
|
+
def with_data_format(new_data_format)
|
|
116
|
+
self.class.new(
|
|
117
|
+
instruction: @instruction,
|
|
118
|
+
input_schema: @input_schema,
|
|
119
|
+
output_schema: @output_schema,
|
|
120
|
+
few_shot_examples: @few_shot_examples,
|
|
121
|
+
signature_class_name: @signature_class_name,
|
|
122
|
+
schema_format: @schema_format,
|
|
123
|
+
signature_class: @signature_class,
|
|
124
|
+
data_format: new_data_format
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
|
|
110
128
|
# Core prompt rendering methods
|
|
111
129
|
sig { returns(String) }
|
|
112
130
|
def render_system_prompt
|
|
@@ -233,15 +251,6 @@ module DSPy
|
|
|
233
251
|
sections.join("\n")
|
|
234
252
|
end
|
|
235
253
|
|
|
236
|
-
# Generate messages for LM adapter
|
|
237
|
-
sig { params(input_values: T::Hash[Symbol, T.untyped]).returns(T::Array[T::Hash[Symbol, String]]) }
|
|
238
|
-
def to_messages(input_values)
|
|
239
|
-
[
|
|
240
|
-
{ role: 'system', content: render_system_prompt },
|
|
241
|
-
{ role: 'user', content: render_user_prompt(input_values) }
|
|
242
|
-
]
|
|
243
|
-
end
|
|
244
|
-
|
|
245
254
|
# Serialization for persistence and optimization
|
|
246
255
|
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
247
256
|
def to_h
|
|
@@ -280,10 +289,6 @@ module DSPy
|
|
|
280
289
|
).returns(Prompt)
|
|
281
290
|
end
|
|
282
291
|
def self.from_signature(signature_class, schema_format: nil, data_format: nil)
|
|
283
|
-
lm = DSPy.config.lm
|
|
284
|
-
schema_format ||= lm&.schema_format || :json
|
|
285
|
-
data_format ||= (lm&.respond_to?(:data_format) ? lm.data_format : nil) || :json
|
|
286
|
-
|
|
287
292
|
new(
|
|
288
293
|
instruction: signature_class.description || "Complete this task.",
|
|
289
294
|
input_schema: signature_class.input_json_schema,
|
|
@@ -506,5 +511,20 @@ module DSPy
|
|
|
506
511
|
base = 'value' if base.empty?
|
|
507
512
|
"example_#{base}"
|
|
508
513
|
end
|
|
514
|
+
|
|
515
|
+
def resolve_schema_format(schema_format)
|
|
516
|
+
return schema_format unless schema_format.nil?
|
|
517
|
+
|
|
518
|
+
lm = DSPy.respond_to?(:current_lm) ? DSPy.current_lm : DSPy.config.lm
|
|
519
|
+
lm&.schema_format || :json
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
def resolve_data_format(data_format)
|
|
523
|
+
return data_format unless data_format.nil?
|
|
524
|
+
|
|
525
|
+
lm = DSPy.respond_to?(:current_lm) ? DSPy.current_lm : DSPy.config.lm
|
|
526
|
+
lm_format = lm&.respond_to?(:data_format) ? lm.data_format : nil
|
|
527
|
+
lm_format || :json
|
|
528
|
+
end
|
|
509
529
|
end
|
|
510
530
|
end
|
|
@@ -160,7 +160,7 @@ module DSPy
|
|
|
160
160
|
DSPy.current_lm,
|
|
161
161
|
verbose: @config.verbose
|
|
162
162
|
)
|
|
163
|
-
rescue => e
|
|
163
|
+
rescue StandardError => e
|
|
164
164
|
DSPy.logger.warn("Failed to generate dataset summary: #{e.message}")
|
|
165
165
|
@dataset_summary = nil
|
|
166
166
|
end
|
|
@@ -189,7 +189,7 @@ module DSPy
|
|
|
189
189
|
# This is a simplified version - could be enhanced with method_source gem
|
|
190
190
|
code = "Program: #{klass.name}\nSource: #{file}:#{line}"
|
|
191
191
|
code
|
|
192
|
-
rescue => e
|
|
192
|
+
rescue StandardError => e
|
|
193
193
|
DSPy.logger.warn("Could not extract program source: #{e.message}")
|
|
194
194
|
nil
|
|
195
195
|
end
|
|
@@ -506,7 +506,7 @@ module DSPy
|
|
|
506
506
|
instruction = result.instruction.strip
|
|
507
507
|
|
|
508
508
|
candidates << instruction if instruction.length > 0
|
|
509
|
-
rescue => error
|
|
509
|
+
rescue StandardError => error
|
|
510
510
|
DSPy.logger.warn("Failed to generate instruction candidate #{i + 1}: #{error.message}")
|
|
511
511
|
end
|
|
512
512
|
end
|
data/lib/dspy/re_act.rb
CHANGED
|
@@ -33,21 +33,6 @@ module DSPy
|
|
|
33
33
|
}
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
|
-
# Base class for ReAct thought generation - will be customized per input type
|
|
37
|
-
class ThoughtBase < DSPy::Signature
|
|
38
|
-
description "Generate a thought about what to do next to process the given inputs."
|
|
39
|
-
|
|
40
|
-
output do
|
|
41
|
-
const :thought, String,
|
|
42
|
-
description: "Reasoning about what to do next, considering the history and observations."
|
|
43
|
-
const :action, String,
|
|
44
|
-
description: "The action to take. MUST be one of the tool names listed in `available_tools` input, or the literal string \"finish\" to provide the final answer."
|
|
45
|
-
const :tool_input, ToolInput,
|
|
46
|
-
description: "Input for the chosen tool action. Required when action is a tool name. MUST be a JSON object matching the tool's parameter schema. Set to null when action is \"finish\"."
|
|
47
|
-
const :final_answer, T.nilable(String),
|
|
48
|
-
description: "The final answer to return. Required when action is \"finish\". Must match the expected output type. Set to null when action is a tool name."
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
36
|
|
|
52
37
|
class NextStep < T::Enum
|
|
53
38
|
enums do
|
|
@@ -56,18 +41,6 @@ module DSPy
|
|
|
56
41
|
end
|
|
57
42
|
end
|
|
58
43
|
|
|
59
|
-
# Base class for observation processing - will be customized per input type
|
|
60
|
-
class ReActObservationBase < DSPy::Signature
|
|
61
|
-
description "Process the observation from a tool and decide what to do next."
|
|
62
|
-
|
|
63
|
-
output do
|
|
64
|
-
const :interpretation, String,
|
|
65
|
-
description: "Interpretation of the observation"
|
|
66
|
-
const :next_step, NextStep,
|
|
67
|
-
description: "What to do next: '#{NextStep::Continue}' or '#{NextStep::Finish}'"
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
44
|
# ReAct Agent using Sorbet signatures
|
|
72
45
|
class ReAct < Predict
|
|
73
46
|
extend T::Sig
|
|
@@ -731,113 +704,6 @@ module DSPy
|
|
|
731
704
|
end
|
|
732
705
|
end
|
|
733
706
|
|
|
734
|
-
# Checks if a type is a scalar (primitives that don't need special serialization)
|
|
735
|
-
sig { params(type_object: T.untyped).returns(T::Boolean) }
|
|
736
|
-
def scalar_type?(type_object)
|
|
737
|
-
case type_object
|
|
738
|
-
when T::Types::Simple
|
|
739
|
-
scalar_classes = [String, Integer, Float, Numeric, TrueClass, FalseClass]
|
|
740
|
-
scalar_classes.any? { |klass| type_object.raw_type == klass || type_object.raw_type <= klass }
|
|
741
|
-
when T::Types::Union
|
|
742
|
-
# Union is scalar if all its types are scalars
|
|
743
|
-
type_object.types.all? { |t| scalar_type?(t) }
|
|
744
|
-
else
|
|
745
|
-
false
|
|
746
|
-
end
|
|
747
|
-
end
|
|
748
|
-
|
|
749
|
-
# Checks if a type is structured (arrays, hashes, structs that need type preservation)
|
|
750
|
-
sig { params(type_object: T.untyped).returns(T::Boolean) }
|
|
751
|
-
def structured_type?(type_object)
|
|
752
|
-
return true if type_object.is_a?(T::Types::TypedArray)
|
|
753
|
-
return true if type_object.is_a?(T::Types::TypedHash)
|
|
754
|
-
|
|
755
|
-
if type_object.is_a?(T::Types::Simple)
|
|
756
|
-
raw_type = type_object.raw_type
|
|
757
|
-
return true if raw_type.respond_to?(:<=) && raw_type <= T::Struct
|
|
758
|
-
end
|
|
759
|
-
|
|
760
|
-
# For union types (like T.nilable(T::Array[...])), check if any non-nil type is structured
|
|
761
|
-
if type_object.is_a?(T::Types::Union)
|
|
762
|
-
non_nil_types = type_object.types.reject { |t| t.is_a?(T::Types::Simple) && t.raw_type == NilClass }
|
|
763
|
-
return non_nil_types.any? { |t| structured_type?(t) }
|
|
764
|
-
end
|
|
765
|
-
|
|
766
|
-
false
|
|
767
|
-
end
|
|
768
|
-
|
|
769
|
-
# Checks if a type is String or compatible with String (e.g., T.any(String, ...) or T.nilable(String))
|
|
770
|
-
sig { params(type_object: T.untyped).returns(T::Boolean) }
|
|
771
|
-
def string_type?(type_object)
|
|
772
|
-
case type_object
|
|
773
|
-
when T::Types::Simple
|
|
774
|
-
type_object.raw_type == String
|
|
775
|
-
when T::Types::Union
|
|
776
|
-
# Check if any of the union types is String
|
|
777
|
-
type_object.types.any? { |t| t.is_a?(T::Types::Simple) && t.raw_type == String }
|
|
778
|
-
else
|
|
779
|
-
false
|
|
780
|
-
end
|
|
781
|
-
end
|
|
782
|
-
|
|
783
|
-
# Alias for backward compatibility
|
|
784
|
-
alias string_compatible_type? string_type?
|
|
785
|
-
|
|
786
|
-
# Get a readable type name from a Sorbet type object
|
|
787
|
-
sig { params(type_object: T.untyped).returns(String) }
|
|
788
|
-
def type_name(type_object)
|
|
789
|
-
case type_object
|
|
790
|
-
when T::Types::TypedArray
|
|
791
|
-
element_type = type_object.type
|
|
792
|
-
"T::Array[#{type_name(element_type)}]"
|
|
793
|
-
when T::Types::TypedHash
|
|
794
|
-
"T::Hash"
|
|
795
|
-
when T::Types::Simple
|
|
796
|
-
type_object.raw_type.to_s
|
|
797
|
-
when T::Types::Union
|
|
798
|
-
types_str = type_object.types.map { |t| type_name(t) }.join(', ')
|
|
799
|
-
"T.any(#{types_str})"
|
|
800
|
-
else
|
|
801
|
-
type_object.to_s
|
|
802
|
-
end
|
|
803
|
-
end
|
|
804
|
-
|
|
805
|
-
# Returns an appropriate default value for a given Sorbet type
|
|
806
|
-
# This is used when max iterations is reached without a successful completion
|
|
807
|
-
sig { params(type_object: T.untyped).returns(T.untyped) }
|
|
808
|
-
def default_value_for_type(type_object)
|
|
809
|
-
# Handle TypedArray (T::Array[...])
|
|
810
|
-
if type_object.is_a?(T::Types::TypedArray)
|
|
811
|
-
return []
|
|
812
|
-
end
|
|
813
|
-
|
|
814
|
-
# Handle TypedHash (T::Hash[...])
|
|
815
|
-
if type_object.is_a?(T::Types::TypedHash)
|
|
816
|
-
return {}
|
|
817
|
-
end
|
|
818
|
-
|
|
819
|
-
# Handle simple types
|
|
820
|
-
case type_object
|
|
821
|
-
when T::Types::Simple
|
|
822
|
-
raw_type = type_object.raw_type
|
|
823
|
-
case raw_type.to_s
|
|
824
|
-
when 'String' then ''
|
|
825
|
-
when 'Integer' then 0
|
|
826
|
-
when 'Float' then 0.0
|
|
827
|
-
when 'TrueClass', 'FalseClass' then false
|
|
828
|
-
else
|
|
829
|
-
# For T::Struct types, return nil as fallback
|
|
830
|
-
nil
|
|
831
|
-
end
|
|
832
|
-
when T::Types::Union
|
|
833
|
-
# For unions, return nil (assuming it's nilable) or first non-nil default
|
|
834
|
-
nil
|
|
835
|
-
else
|
|
836
|
-
# Default fallback for unknown types
|
|
837
|
-
nil
|
|
838
|
-
end
|
|
839
|
-
end
|
|
840
|
-
|
|
841
707
|
# Tool execution method
|
|
842
708
|
sig { params(action: String, tool_input: ToolInput).returns(T.untyped) }
|
|
843
709
|
def execute_action(action, tool_input)
|
|
@@ -855,34 +721,6 @@ module DSPy
|
|
|
855
721
|
end
|
|
856
722
|
end
|
|
857
723
|
|
|
858
|
-
sig { params(output: T.untyped).void }
|
|
859
|
-
def validate_output_schema!(output)
|
|
860
|
-
# Validate that output is an instance of the enhanced output struct
|
|
861
|
-
unless output.is_a?(@enhanced_output_struct)
|
|
862
|
-
raise "Output must be an instance of #{@enhanced_output_struct}, got #{output.class}"
|
|
863
|
-
end
|
|
864
|
-
|
|
865
|
-
# Validate original signature output fields are present
|
|
866
|
-
@original_signature_class.output_struct_class.props.each do |field_name, _prop|
|
|
867
|
-
unless output.respond_to?(field_name)
|
|
868
|
-
raise "Missing required field: #{field_name}"
|
|
869
|
-
end
|
|
870
|
-
end
|
|
871
|
-
|
|
872
|
-
# Validate ReAct-specific fields
|
|
873
|
-
unless output.respond_to?(:history) && output.history.is_a?(Array)
|
|
874
|
-
raise "Missing or invalid history field"
|
|
875
|
-
end
|
|
876
|
-
|
|
877
|
-
unless output.respond_to?(:iterations) && output.iterations.is_a?(Integer)
|
|
878
|
-
raise "Missing or invalid iterations field"
|
|
879
|
-
end
|
|
880
|
-
|
|
881
|
-
unless output.respond_to?(:tools_used) && output.tools_used.is_a?(Array)
|
|
882
|
-
raise "Missing or invalid tools_used field"
|
|
883
|
-
end
|
|
884
|
-
end
|
|
885
|
-
|
|
886
724
|
sig { override.returns(T::Hash[Symbol, T.untyped]) }
|
|
887
725
|
def generate_example_output
|
|
888
726
|
example = super
|
|
@@ -259,7 +259,7 @@ module DSPy
|
|
|
259
259
|
emit_register_complete_event(signature_version)
|
|
260
260
|
signature_version
|
|
261
261
|
|
|
262
|
-
rescue => error
|
|
262
|
+
rescue StandardError => error
|
|
263
263
|
emit_register_error_event(signature_name, version, error)
|
|
264
264
|
raise
|
|
265
265
|
end
|
|
@@ -313,7 +313,7 @@ module DSPy
|
|
|
313
313
|
emit_deploy_complete_event(deployed_version)
|
|
314
314
|
deployed_version
|
|
315
315
|
|
|
316
|
-
rescue => error
|
|
316
|
+
rescue StandardError => error
|
|
317
317
|
emit_deploy_error_event(signature_name, version, error)
|
|
318
318
|
nil
|
|
319
319
|
end
|
|
@@ -363,7 +363,7 @@ module DSPy
|
|
|
363
363
|
emit_rollback_error_event(signature_name, "No previous version to rollback to")
|
|
364
364
|
nil
|
|
365
365
|
|
|
366
|
-
rescue => error
|
|
366
|
+
rescue StandardError => error
|
|
367
367
|
emit_rollback_error_event(signature_name, error.message)
|
|
368
368
|
nil
|
|
369
369
|
end
|
|
@@ -52,7 +52,7 @@ module DSPy
|
|
|
52
52
|
# Validate vision support if images are present
|
|
53
53
|
if contains_images?(normalized_messages)
|
|
54
54
|
validate_vision_support!
|
|
55
|
-
normalized_messages = format_multimodal_messages(normalized_messages)
|
|
55
|
+
normalized_messages = format_multimodal_messages(normalized_messages, provider)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
chat_instance = create_chat_instance
|
|
@@ -358,32 +358,6 @@ module DSPy
|
|
|
358
358
|
# If DSPy doesn't know about the model, let RubyLLM handle it
|
|
359
359
|
# RubyLLM has its own model registry with capability detection
|
|
360
360
|
end
|
|
361
|
-
|
|
362
|
-
def format_multimodal_messages(messages)
|
|
363
|
-
messages.map do |msg|
|
|
364
|
-
if msg[:content].is_a?(Array)
|
|
365
|
-
formatted_content = msg[:content].map do |item|
|
|
366
|
-
case item[:type]
|
|
367
|
-
when 'text'
|
|
368
|
-
{ type: 'text', text: item[:text] }
|
|
369
|
-
when 'image'
|
|
370
|
-
# Validate and format image for provider
|
|
371
|
-
image = item[:image]
|
|
372
|
-
if image.respond_to?(:validate_for_provider!)
|
|
373
|
-
image.validate_for_provider!(provider)
|
|
374
|
-
end
|
|
375
|
-
item
|
|
376
|
-
else
|
|
377
|
-
item
|
|
378
|
-
end
|
|
379
|
-
end
|
|
380
|
-
|
|
381
|
-
{ role: msg[:role], content: formatted_content }
|
|
382
|
-
else
|
|
383
|
-
msg
|
|
384
|
-
end
|
|
385
|
-
end
|
|
386
|
-
end
|
|
387
361
|
end
|
|
388
362
|
end
|
|
389
363
|
end
|
|
@@ -195,10 +195,10 @@ module DSPy
|
|
|
195
195
|
end
|
|
196
196
|
else
|
|
197
197
|
# Not nilable SimplePairUnion - this is a regular T.any() union
|
|
198
|
-
# Generate
|
|
198
|
+
# Generate anyOf schema for all types (oneOf not supported by Anthropic strict mode)
|
|
199
199
|
if type.respond_to?(:types) && type.types.length > 1
|
|
200
200
|
{
|
|
201
|
-
|
|
201
|
+
anyOf: type.types.map { |t| type_to_json_schema_internal(t, visited, definitions) },
|
|
202
202
|
description: "Union of multiple types"
|
|
203
203
|
}
|
|
204
204
|
else
|
|
@@ -237,14 +237,14 @@ module DSPy
|
|
|
237
237
|
# Non-nilable single type union (shouldn't happen in practice)
|
|
238
238
|
type_to_json_schema_internal(non_nil_types.first, visited, definitions)
|
|
239
239
|
elsif non_nil_types.size > 1
|
|
240
|
-
# Handle complex unions with oneOf
|
|
240
|
+
# Handle complex unions with anyOf (oneOf not supported by Anthropic strict mode)
|
|
241
241
|
base_schema = {
|
|
242
|
-
|
|
242
|
+
anyOf: non_nil_types.map { |t| type_to_json_schema_internal(t, visited, definitions) },
|
|
243
243
|
description: "Union of multiple types"
|
|
244
244
|
}
|
|
245
245
|
if is_nilable
|
|
246
246
|
# Add null as an option for complex nilable unions
|
|
247
|
-
base_schema[:
|
|
247
|
+
base_schema[:anyOf] << { type: "null" }
|
|
248
248
|
end
|
|
249
249
|
base_schema
|
|
250
250
|
else
|
|
@@ -335,7 +335,8 @@ module DSPy
|
|
|
335
335
|
type: "object",
|
|
336
336
|
properties: properties,
|
|
337
337
|
required: required,
|
|
338
|
-
description: "#{struct_name} struct"
|
|
338
|
+
description: "#{struct_name} struct",
|
|
339
|
+
additionalProperties: false
|
|
339
340
|
}
|
|
340
341
|
|
|
341
342
|
# Add this struct's schema to definitions for $defs
|
data/lib/dspy/schema/version.rb
CHANGED
data/lib/dspy/schema_adapters.rb
CHANGED
|
@@ -198,7 +198,7 @@ module DSPy
|
|
|
198
198
|
emit_save_complete_event(saved_program)
|
|
199
199
|
saved_program
|
|
200
200
|
|
|
201
|
-
rescue => error
|
|
201
|
+
rescue StandardError => error
|
|
202
202
|
emit_save_error_event(program_id, error)
|
|
203
203
|
raise
|
|
204
204
|
end
|
|
@@ -223,7 +223,7 @@ module DSPy
|
|
|
223
223
|
emit_load_complete_event(saved_program)
|
|
224
224
|
saved_program
|
|
225
225
|
|
|
226
|
-
rescue => error
|
|
226
|
+
rescue StandardError => error
|
|
227
227
|
emit_load_error_event(program_id, error)
|
|
228
228
|
nil
|
|
229
229
|
end
|
|
@@ -16,12 +16,12 @@ module DSPy
|
|
|
16
16
|
output_schema: T::Hash[Symbol, T.untyped],
|
|
17
17
|
few_shot_examples: T::Array[T.untyped],
|
|
18
18
|
signature_class_name: T.nilable(String),
|
|
19
|
-
schema_format: Symbol,
|
|
19
|
+
schema_format: T.nilable(Symbol),
|
|
20
20
|
signature_class: T.nilable(T.class_of(Signature)),
|
|
21
|
-
data_format: Symbol
|
|
21
|
+
data_format: T.nilable(Symbol)
|
|
22
22
|
).void
|
|
23
23
|
end
|
|
24
|
-
def initialize(instruction:, input_schema:, output_schema:, few_shot_examples: [], signature_class_name: nil, schema_format:
|
|
24
|
+
def initialize(instruction:, input_schema:, output_schema:, few_shot_examples: [], signature_class_name: nil, schema_format: nil, signature_class: nil, data_format: nil)
|
|
25
25
|
normalized_examples = few_shot_examples.map do |example|
|
|
26
26
|
case example
|
|
27
27
|
when FewShotExample
|
|
@@ -360,7 +360,7 @@ module DSPy
|
|
|
360
360
|
)
|
|
361
361
|
successful_demos << demo
|
|
362
362
|
end
|
|
363
|
-
rescue => e
|
|
363
|
+
rescue StandardError => e
|
|
364
364
|
# Continue on errors
|
|
365
365
|
DSPy.logger.warn("Bootstrap error: #{e.message}") if DSPy.logger
|
|
366
366
|
end
|
|
@@ -513,7 +513,7 @@ module DSPy
|
|
|
513
513
|
emit_bootstrap_example_event(index, false, "Prediction did not match expected output")
|
|
514
514
|
end
|
|
515
515
|
|
|
516
|
-
rescue => error
|
|
516
|
+
rescue StandardError => error
|
|
517
517
|
error_count += 1
|
|
518
518
|
failed << example
|
|
519
519
|
emit_bootstrap_example_event(index, false, error.message)
|
|
@@ -105,7 +105,7 @@ module DSPy
|
|
|
105
105
|
else
|
|
106
106
|
"Failed to list issues: #{result[:error]}"
|
|
107
107
|
end
|
|
108
|
-
rescue => e
|
|
108
|
+
rescue StandardError => e
|
|
109
109
|
"Error listing issues: #{e.message}"
|
|
110
110
|
end
|
|
111
111
|
|
|
@@ -140,7 +140,7 @@ module DSPy
|
|
|
140
140
|
else
|
|
141
141
|
"Failed to list pull requests: #{result[:error]}"
|
|
142
142
|
end
|
|
143
|
-
rescue => e
|
|
143
|
+
rescue StandardError => e
|
|
144
144
|
"Error listing pull requests: #{e.message}"
|
|
145
145
|
end
|
|
146
146
|
|
|
@@ -159,7 +159,7 @@ module DSPy
|
|
|
159
159
|
else
|
|
160
160
|
"Failed to get issue: #{result[:error]}"
|
|
161
161
|
end
|
|
162
|
-
rescue => e
|
|
162
|
+
rescue StandardError => e
|
|
163
163
|
"Error getting issue: #{e.message}"
|
|
164
164
|
end
|
|
165
165
|
|
|
@@ -178,7 +178,7 @@ module DSPy
|
|
|
178
178
|
else
|
|
179
179
|
"Failed to get pull request: #{result[:error]}"
|
|
180
180
|
end
|
|
181
|
-
rescue => e
|
|
181
|
+
rescue StandardError => e
|
|
182
182
|
"Error getting pull request: #{e.message}"
|
|
183
183
|
end
|
|
184
184
|
|
|
@@ -214,7 +214,7 @@ module DSPy
|
|
|
214
214
|
else
|
|
215
215
|
"API request failed: #{result[:error]}"
|
|
216
216
|
end
|
|
217
|
-
rescue => e
|
|
217
|
+
rescue StandardError => e
|
|
218
218
|
"Error making API request: #{e.message}"
|
|
219
219
|
end
|
|
220
220
|
|
|
@@ -231,7 +231,7 @@ module DSPy
|
|
|
231
231
|
else
|
|
232
232
|
"Failed to fetch traffic views: #{result[:error]}"
|
|
233
233
|
end
|
|
234
|
-
rescue => e
|
|
234
|
+
rescue StandardError => e
|
|
235
235
|
"Error fetching traffic views: #{e.message}"
|
|
236
236
|
end
|
|
237
237
|
|
|
@@ -248,7 +248,7 @@ module DSPy
|
|
|
248
248
|
else
|
|
249
249
|
"Failed to fetch traffic clones: #{result[:error]}"
|
|
250
250
|
end
|
|
251
|
-
rescue => e
|
|
251
|
+
rescue StandardError => e
|
|
252
252
|
"Error fetching traffic clones: #{e.message}"
|
|
253
253
|
end
|
|
254
254
|
|
|
@@ -52,7 +52,7 @@ module DSPy
|
|
|
52
52
|
else
|
|
53
53
|
result
|
|
54
54
|
end
|
|
55
|
-
rescue => e
|
|
55
|
+
rescue StandardError => e
|
|
56
56
|
"Error running grep: #{e.message}"
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -92,7 +92,7 @@ module DSPy
|
|
|
92
92
|
else
|
|
93
93
|
result
|
|
94
94
|
end
|
|
95
|
-
rescue => e
|
|
95
|
+
rescue StandardError => e
|
|
96
96
|
"Error running ripgrep: #{e.message}"
|
|
97
97
|
end
|
|
98
98
|
|
data/lib/dspy/tools/toolset.rb
CHANGED
data/lib/dspy/version.rb
CHANGED
data/lib/dspy.rb
CHANGED
|
@@ -141,7 +141,7 @@ module DSPy
|
|
|
141
141
|
# Events are instant moments in time, not ongoing operations
|
|
142
142
|
span = DSPy::Observability.start_span(event_name, flattened_attributes)
|
|
143
143
|
DSPy::Observability.finish_span(span) if span
|
|
144
|
-
rescue => e
|
|
144
|
+
rescue StandardError => e
|
|
145
145
|
# Log error but don't let it break the event system
|
|
146
146
|
# Use emit_log directly to avoid infinite recursion
|
|
147
147
|
emit_log('event.span_creation_error', {
|
|
@@ -221,8 +221,6 @@ require_relative 'dspy/lm'
|
|
|
221
221
|
require_relative 'dspy/image'
|
|
222
222
|
require_relative 'dspy/prediction'
|
|
223
223
|
require_relative 'dspy/predict'
|
|
224
|
-
require_relative 'dspy/events/subscribers'
|
|
225
|
-
require_relative 'dspy/events/subscriber_mixin'
|
|
226
224
|
require_relative 'dspy/chain_of_thought'
|
|
227
225
|
require_relative 'dspy/re_act'
|
|
228
226
|
require_relative 'dspy/evals'
|
|
@@ -248,7 +246,6 @@ begin
|
|
|
248
246
|
rescue LoadError
|
|
249
247
|
end
|
|
250
248
|
require_relative 'dspy/tools'
|
|
251
|
-
require_relative 'dspy/memory'
|
|
252
249
|
|
|
253
250
|
begin
|
|
254
251
|
require 'dspy/datasets'
|