dspy 0.29.1 → 0.30.1

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +45 -0
  3. data/README.md +159 -95
  4. data/lib/dspy/callbacks.rb +93 -19
  5. data/lib/dspy/context.rb +101 -5
  6. data/lib/dspy/errors.rb +19 -1
  7. data/lib/dspy/{datasets.rb → evals/version.rb} +2 -3
  8. data/lib/dspy/{evaluate.rb → evals.rb} +373 -110
  9. data/lib/dspy/mixins/instruction_updatable.rb +22 -0
  10. data/lib/dspy/module.rb +213 -17
  11. data/lib/dspy/observability.rb +40 -182
  12. data/lib/dspy/predict.rb +10 -2
  13. data/lib/dspy/propose/dataset_summary_generator.rb +28 -18
  14. data/lib/dspy/re_act.rb +21 -0
  15. data/lib/dspy/schema/sorbet_json_schema.rb +302 -0
  16. data/lib/dspy/schema/version.rb +7 -0
  17. data/lib/dspy/schema.rb +4 -0
  18. data/lib/dspy/structured_outputs_prompt.rb +48 -0
  19. data/lib/dspy/support/warning_filters.rb +27 -0
  20. data/lib/dspy/teleprompt/gepa.rb +9 -588
  21. data/lib/dspy/teleprompt/instruction_updates.rb +94 -0
  22. data/lib/dspy/teleprompt/teleprompter.rb +6 -6
  23. data/lib/dspy/teleprompt/utils.rb +5 -65
  24. data/lib/dspy/type_system/sorbet_json_schema.rb +2 -299
  25. data/lib/dspy/version.rb +1 -1
  26. data/lib/dspy.rb +39 -7
  27. metadata +18 -61
  28. data/lib/dspy/code_act.rb +0 -477
  29. data/lib/dspy/datasets/ade.rb +0 -90
  30. data/lib/dspy/observability/async_span_processor.rb +0 -250
  31. data/lib/dspy/observability/observation_type.rb +0 -65
  32. data/lib/dspy/optimizers/gaussian_process.rb +0 -141
  33. data/lib/dspy/teleprompt/mipro_v2.rb +0 -1672
  34. data/lib/gepa/api.rb +0 -61
  35. data/lib/gepa/core/engine.rb +0 -226
  36. data/lib/gepa/core/evaluation_batch.rb +0 -26
  37. data/lib/gepa/core/result.rb +0 -92
  38. data/lib/gepa/core/state.rb +0 -231
  39. data/lib/gepa/logging/experiment_tracker.rb +0 -54
  40. data/lib/gepa/logging/logger.rb +0 -57
  41. data/lib/gepa/logging.rb +0 -9
  42. data/lib/gepa/proposer/base.rb +0 -27
  43. data/lib/gepa/proposer/merge_proposer.rb +0 -424
  44. data/lib/gepa/proposer/reflective_mutation/base.rb +0 -48
  45. data/lib/gepa/proposer/reflective_mutation/reflective_mutation.rb +0 -188
  46. data/lib/gepa/strategies/batch_sampler.rb +0 -91
  47. data/lib/gepa/strategies/candidate_selector.rb +0 -97
  48. data/lib/gepa/strategies/component_selector.rb +0 -57
  49. data/lib/gepa/strategies/instruction_proposal.rb +0 -120
  50. data/lib/gepa/telemetry.rb +0 -122
  51. data/lib/gepa/utils/pareto.rb +0 -119
  52. data/lib/gepa.rb +0 -21
@@ -1,119 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
- require 'set'
5
- require 'sorbet-runtime'
6
-
7
- module GEPA
8
- module Utils
9
- module Pareto
10
- extend T::Sig
11
-
12
- sig { params(value: T.untyped).returns(T.untyped) }
13
- def self.json_default(value)
14
- value.is_a?(Hash) ? value.transform_keys(&:to_s) : JSON.parse(value.to_json)
15
- rescue StandardError
16
- { value: value.to_s }
17
- end
18
-
19
- sig { params(values: T::Array[Float]).returns(Integer) }
20
- def self.idxmax(values)
21
- raise ArgumentError, 'values must not be empty' if values.empty?
22
-
23
- values.each_with_index.max_by { |score, _i| score }&.last || 0
24
- end
25
-
26
- sig do
27
- params(
28
- program_at_pareto_front_valset: T::Array[T.untyped],
29
- scores: T.nilable(T::Hash[Integer, Float])
30
- ).returns(T::Array[T.untyped])
31
- end
32
- def self.remove_dominated_programs(program_at_pareto_front_valset, scores: nil)
33
- normalized_fronts = program_at_pareto_front_valset.map { |front| front.to_a }
34
-
35
- frequency = Hash.new(0)
36
- normalized_fronts.each do |front|
37
- front.each { |program_idx| frequency[program_idx] += 1 }
38
- end
39
-
40
- all_programs = frequency.keys
41
- scores ||= all_programs.to_h { |idx| [idx, 1.0] }
42
-
43
- sorted_programs = all_programs.sort_by { |idx| scores.fetch(idx, 0.0) }
44
-
45
- dominated = Set.new
46
- loop do
47
- found = false
48
- sorted_programs.each do |candidate|
49
- next if dominated.include?(candidate)
50
- next unless dominated?(candidate, sorted_programs.to_set, dominated, normalized_fronts)
51
-
52
- dominated.add(candidate)
53
- found = true
54
- break
55
- end
56
- break unless found
57
- end
58
-
59
- dominators = sorted_programs.reject { |idx| dominated.include?(idx) }
60
- dominators_set = dominators.to_set
61
-
62
- normalized_fronts.map do |front|
63
- front.select { |idx| dominators_set.include?(idx) }
64
- end
65
- end
66
-
67
- sig do
68
- params(
69
- pareto_front_programs: T::Array[T.untyped],
70
- train_val_weighted_scores: T::Hash[Integer, Float]
71
- ).returns(T::Array[Integer])
72
- end
73
- def self.find_dominator_programs(pareto_front_programs, train_val_weighted_scores)
74
- cleaned_frontiers = remove_dominated_programs(pareto_front_programs, scores: train_val_weighted_scores)
75
- cleaned_frontiers.flat_map(&:to_a).uniq
76
- end
77
-
78
- sig do
79
- params(
80
- pareto_front_programs: T::Array[T.untyped],
81
- weighted_scores: T::Hash[Integer, Float],
82
- rng: Random
83
- ).returns(Integer)
84
- end
85
- def self.select_program_candidate_from_pareto_front(pareto_front_programs, weighted_scores, rng)
86
- cleaned_frontiers = remove_dominated_programs(pareto_front_programs, scores: weighted_scores)
87
- frequency = Hash.new(0)
88
- cleaned_frontiers.each do |front|
89
- front.each { |idx| frequency[idx] += 1 }
90
- end
91
- raise ArgumentError, 'pareto front is empty' if frequency.empty?
92
-
93
- sampling_list = frequency.flat_map { |idx, freq| [idx] * freq }
94
- sampling_list[rng.rand(sampling_list.length)]
95
- end
96
-
97
- class << self
98
- extend T::Sig
99
- private
100
-
101
- sig do
102
- params(
103
- candidate: Integer,
104
- program_set: Set,
105
- dominated: Set,
106
- pareto_fronts: T::Array[T::Array[Integer]]
107
- ).returns(T::Boolean)
108
- end
109
- def dominated?(candidate, program_set, dominated, pareto_fronts)
110
- candidate_fronts = pareto_fronts.select { |front| front.include?(candidate) }
111
- candidate_fronts.all? do |front|
112
- remaining = front.reject { |idx| idx == candidate || dominated.include?(idx) }
113
- remaining.any? { |other| program_set.include?(other) }
114
- end
115
- end
116
- end
117
- end
118
- end
119
- end
data/lib/gepa.rb DELETED
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'gepa/telemetry'
4
- require_relative 'gepa/logging'
5
- require_relative 'gepa/utils/pareto'
6
- require_relative 'gepa/strategies/batch_sampler'
7
- require_relative 'gepa/strategies/candidate_selector'
8
- require_relative 'gepa/strategies/component_selector'
9
- require_relative 'gepa/strategies/instruction_proposal'
10
- require_relative 'gepa/core/evaluation_batch'
11
- require_relative 'gepa/core/result'
12
- require_relative 'gepa/core/state'
13
- require_relative 'gepa/core/engine'
14
- require_relative 'gepa/proposer/base'
15
- require_relative 'gepa/proposer/reflective_mutation/base'
16
- require_relative 'gepa/proposer/reflective_mutation/reflective_mutation'
17
- require_relative 'gepa/proposer/merge_proposer'
18
- require_relative 'gepa/api'
19
-
20
- module GEPA
21
- end