dspy 0.6.3 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae1673ad31bc71e2573800124ebb74ea807cd94a1c14b9b58f3de94b7f62363a
4
- data.tar.gz: f52d96924b536e5941ff34b45f1080ddb08dc9243095df51f11352cb65979ba1
3
+ metadata.gz: 44671af9a40e3f452983f616a3df0770babbe5d9cde85c18c9ace6fe618fcfe5
4
+ data.tar.gz: e3ba107fed63ba58dfa9b3f707d682acc88a6e7a1c8a72a89a46fbb19c82347c
5
5
  SHA512:
6
- metadata.gz: 98f1d7b285f9342b8dfc82cdc7606d2a4c8cbdb1df86713b7176a389893f7c652e7c5df473ddcf42335ab37a2cfffe35e9519310b45be396c9bfe8847c7fabc1
7
- data.tar.gz: cbee70fb3afc5b5b7dce3caf2efbca258d5cbd12680f950fe52be30bd84754369b620c21617315c04a62e2f982fe485b0c05f7ed30676007c19527715c3fc9c0
6
+ metadata.gz: bda31c209ff68af39500de5b8f562fb173e08a5fc41863cd96b89f4f0e8be62cadbc73fc31fc61567d8d8e2e0afce86e4710028fbdeba8a4e6709811be73c754
7
+ data.tar.gz: a4823fcc2341684b7c0b98b00e2c7dbe9847b61d3b3fde69e3cd31767478659e75fd8c432be6de44290a557f30e382836f671e7fe83edc0cab07f037ab2f6e7c
@@ -24,7 +24,12 @@ module DSPy
24
24
 
25
25
  def validate_configuration!
26
26
  raise ConfigurationError, "Model is required" if model.nil? || model.empty?
27
- raise ConfigurationError, "API key is required" if api_key.nil? || api_key.empty?
27
+ end
28
+
29
+ def validate_api_key!(api_key, provider)
30
+ if api_key.nil? || api_key.to_s.strip.empty?
31
+ raise MissingAPIKeyError.new(provider)
32
+ end
28
33
  end
29
34
 
30
35
  # Helper method to normalize message format
@@ -7,6 +7,7 @@ module DSPy
7
7
  class AnthropicAdapter < Adapter
8
8
  def initialize(model:, api_key:)
9
9
  super
10
+ validate_api_key!(api_key, 'anthropic')
10
11
  @client = Anthropic::Client.new(api_key: api_key)
11
12
  end
12
13
 
@@ -7,6 +7,7 @@ module DSPy
7
7
  class OpenAIAdapter < Adapter
8
8
  def initialize(model:, api_key:)
9
9
  super
10
+ validate_api_key!(api_key, 'openai')
10
11
  @client = OpenAI::Client.new(api_key: api_key)
11
12
  end
12
13
 
@@ -6,5 +6,18 @@ module DSPy
6
6
  class AdapterError < Error; end
7
7
  class UnsupportedProviderError < Error; end
8
8
  class ConfigurationError < Error; end
9
+
10
+ # Raised when API key is missing or invalid
11
+ class MissingAPIKeyError < Error
12
+ def initialize(provider)
13
+ env_var = case provider
14
+ when 'openai' then 'OPENAI_API_KEY'
15
+ when 'anthropic' then 'ANTHROPIC_API_KEY'
16
+ else "#{provider.upcase}_API_KEY"
17
+ end
18
+
19
+ super("API key is required but was not provided. Set it via the api_key parameter or #{env_var} environment variable.")
20
+ end
21
+ end
9
22
  end
10
23
  end
data/lib/dspy/predict.rb CHANGED
@@ -115,6 +115,9 @@ module DSPy
115
115
  output_attributes = output_attributes.transform_keys(&:to_sym)
116
116
  output_props = @signature_class.output_struct_class.props
117
117
 
118
+ # Apply defaults for missing fields
119
+ output_attributes = apply_defaults_to_output(output_attributes)
120
+
118
121
  coerce_output_attributes(output_attributes, output_props)
119
122
  end
120
123
 
@@ -143,5 +146,22 @@ module DSPy
143
146
  output: output_props
144
147
  })
145
148
  end
149
+
150
+ # Applies default values to missing output fields
151
+ sig { params(output_attributes: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
152
+ def apply_defaults_to_output(output_attributes)
153
+ return output_attributes unless @signature_class.respond_to?(:output_field_descriptors)
154
+
155
+ field_descriptors = @signature_class.output_field_descriptors
156
+
157
+ field_descriptors.each do |field_name, descriptor|
158
+ # Only apply default if field is missing and has a default
159
+ if !output_attributes.key?(field_name) && descriptor.has_default
160
+ output_attributes[field_name] = descriptor.default_value
161
+ end
162
+ end
163
+
164
+ output_attributes
165
+ end
146
166
  end
147
167
  end
@@ -20,11 +20,15 @@ module DSPy
20
20
  sig { returns(T::Boolean) }
21
21
  attr_reader :has_default
22
22
 
23
- sig { params(type: T.untyped, description: T.nilable(String), has_default: T::Boolean).void }
24
- def initialize(type, description = nil, has_default = false)
23
+ sig { returns(T.untyped) }
24
+ attr_reader :default_value
25
+
26
+ sig { params(type: T.untyped, description: T.nilable(String), has_default: T::Boolean, default_value: T.untyped).void }
27
+ def initialize(type, description = nil, has_default = false, default_value = nil)
25
28
  @type = type
26
29
  @description = description
27
30
  @has_default = has_default
31
+ @default_value = default_value
28
32
  end
29
33
  end
30
34
 
@@ -44,8 +48,8 @@ module DSPy
44
48
  def const(name, type, **kwargs)
45
49
  description = kwargs[:description]
46
50
  has_default = kwargs.key?(:default)
47
- @field_descriptors[name] = FieldDescriptor.new(type, description, has_default)
48
- # Store default for future use if needed
51
+ default_value = kwargs[:default]
52
+ @field_descriptors[name] = FieldDescriptor.new(type, description, has_default, default_value)
49
53
  end
50
54
 
51
55
  sig { returns(T.class_of(T::Struct)) }
@@ -54,7 +58,11 @@ module DSPy
54
58
  Class.new(T::Struct) do
55
59
  extend T::Sig
56
60
  descriptors.each do |name, descriptor|
57
- const name, descriptor.type
61
+ if descriptor.has_default
62
+ const name, descriptor.type, default: descriptor.default_value
63
+ else
64
+ const name, descriptor.type
65
+ end
58
66
  end
59
67
  end
60
68
  end
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.6.3"
4
+ VERSION = "0.7.0"
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.6.3
4
+ version: 0.7.0
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-07-08 00:00:00.000000000 Z
10
+ date: 2025-07-11 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: dry-configurable