dspy 0.29.0 → 0.30.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +45 -0
  3. data/README.md +121 -101
  4. data/lib/dspy/callbacks.rb +74 -19
  5. data/lib/dspy/context.rb +49 -4
  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/observability.rb +40 -182
  11. data/lib/dspy/predict.rb +10 -2
  12. data/lib/dspy/propose/dataset_summary_generator.rb +28 -18
  13. data/lib/dspy/re_act.rb +21 -0
  14. data/lib/dspy/schema/sorbet_json_schema.rb +302 -0
  15. data/lib/dspy/schema/version.rb +7 -0
  16. data/lib/dspy/schema.rb +4 -0
  17. data/lib/dspy/structured_outputs_prompt.rb +48 -0
  18. data/lib/dspy/support/warning_filters.rb +27 -0
  19. data/lib/dspy/teleprompt/gepa.rb +9 -588
  20. data/lib/dspy/teleprompt/instruction_updates.rb +94 -0
  21. data/lib/dspy/teleprompt/teleprompter.rb +6 -6
  22. data/lib/dspy/teleprompt/utils.rb +5 -65
  23. data/lib/dspy/type_system/sorbet_json_schema.rb +2 -299
  24. data/lib/dspy/version.rb +1 -1
  25. data/lib/dspy.rb +33 -7
  26. metadata +14 -60
  27. data/lib/dspy/code_act.rb +0 -477
  28. data/lib/dspy/datasets/ade.rb +0 -90
  29. data/lib/dspy/observability/async_span_processor.rb +0 -250
  30. data/lib/dspy/observability/observation_type.rb +0 -65
  31. data/lib/dspy/optimizers/gaussian_process.rb +0 -141
  32. data/lib/dspy/teleprompt/mipro_v2.rb +0 -1423
  33. data/lib/gepa/api.rb +0 -61
  34. data/lib/gepa/core/engine.rb +0 -226
  35. data/lib/gepa/core/evaluation_batch.rb +0 -26
  36. data/lib/gepa/core/result.rb +0 -92
  37. data/lib/gepa/core/state.rb +0 -231
  38. data/lib/gepa/logging/experiment_tracker.rb +0 -54
  39. data/lib/gepa/logging/logger.rb +0 -57
  40. data/lib/gepa/logging.rb +0 -9
  41. data/lib/gepa/proposer/base.rb +0 -27
  42. data/lib/gepa/proposer/merge_proposer.rb +0 -424
  43. data/lib/gepa/proposer/reflective_mutation/base.rb +0 -48
  44. data/lib/gepa/proposer/reflective_mutation/reflective_mutation.rb +0 -188
  45. data/lib/gepa/strategies/batch_sampler.rb +0 -91
  46. data/lib/gepa/strategies/candidate_selector.rb +0 -97
  47. data/lib/gepa/strategies/component_selector.rb +0 -57
  48. data/lib/gepa/strategies/instruction_proposal.rb +0 -120
  49. data/lib/gepa/telemetry.rb +0 -122
  50. data/lib/gepa/utils/pareto.rb +0 -119
  51. 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