dspy-gemini 1.0.3 → 1.0.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: 0d8c3a914bf14371393cd8666e8fe6dde619beba003ad16513e3ecb077239b06
4
- data.tar.gz: fdd2ee0fd8710a95653626ccf32a529fe491efefcb5bbe3f7c4422586a056733
3
+ metadata.gz: f74542eb4beab2b4b2c3c3931b496c4a0ef8d7e6925fb63dd7bf1b71d770a9c0
4
+ data.tar.gz: 6d8cdd3ffcadbbea59ebc03c0b199fa79e07aac79a07ba9dc29aba1aa39169fa
5
5
  SHA512:
6
- metadata.gz: efedc61fd10498ee0efff8f03d1b55c8f9e2407fe7afaad7b99e2489fb184ebbec468a3ffc85054ece684bcaaa8cd8e112ce4a4a64a9ec32e39ad823d8d1256d
7
- data.tar.gz: 05203eb5b8bc7b61ec438fb65d0c289c59a2cb7a97dc5e8bd64e195f64f183879392d701da50d94af66fc62b81383b8520125a7181850001e4c3cb19b3fed4c0
6
+ metadata.gz: f30d06f707b26c85d0497feb334664f553f7f02f5c5fccfd5ecfd9a4ef32d668f6cb1f567a22a772e8f48a5a7cc7ccc462a96abc8ec354161e722717758574d8
7
+ data.tar.gz: aa30c0732139dc720652735bc5f850a5ba1f39cd2e32082dc0d592a7a61a344143f72160737583cb3e15300a958a87084b7f5612b1029e60dc5559b8cb72b53a
data/README.md CHANGED
@@ -6,95 +6,16 @@
6
6
  [![Documentation](https://img.shields.io/badge/docs-oss.vicente.services%2Fdspy.rb-blue)](https://oss.vicente.services/dspy.rb/)
7
7
  [![Discord](https://img.shields.io/discord/1161519468141355160?label=discord&logo=discord&logoColor=white)](https://discord.gg/zWBhrMqn)
8
8
 
9
- **Build reliable LLM applications in idiomatic Ruby using composable, type-safe modules.**
9
+ **Build typed agents and model-backed programs in Ruby.**
10
10
 
11
- DSPy.rb is the Ruby port of Stanford's [DSPy](https://dspy.ai). Instead of wrestling with brittle prompt strings, you define typed signatures and let the framework handle the rest. Prompts become functions. LLM calls become predictable.
11
+ DSPy.rb brings [DSPy](https://dspy.ai)'s signature, module, agent, and optimizer model to Ruby, with Sorbet types and Ruby-native integrations. A signature declares a task as typed inputs and outputs. A module chooses how to execute it. Ruby composes modules into programs, while `ReAct` adds a bounded loop when the model should choose the next action. DSPy.rb builds the provider request and validates the returned shape.
12
12
 
13
- ```ruby
14
- require 'dspy'
15
-
16
- DSPy.configure do |c|
17
- c.lm = DSPy::LM.new('openai/gpt-4o-mini', api_key: ENV['OPENAI_API_KEY'])
18
- end
19
-
20
- class Summarize < DSPy::Signature
21
- description "Summarize the given text in one sentence."
22
-
23
- input do
24
- const :text, String
25
- end
26
-
27
- output do
28
- const :summary, String
29
- end
30
- end
31
-
32
- summarizer = DSPy::Predict.new(Summarize)
33
- result = summarizer.call(text: "DSPy.rb brings structured LLM programming to Ruby...")
34
- puts result.summary
35
- ```
36
-
37
- That's it. No prompt templates. No JSON parsing. No prayer-based error handling.
38
-
39
- ## Installation
40
-
41
- ```ruby
42
- # Gemfile
43
- gem 'dspy'
44
- gem 'dspy-openai' # For OpenAI, OpenRouter, or Ollama
45
- # gem 'dspy-anthropic' # For Claude
46
- # gem 'dspy-gemini' # For Gemini
47
- # gem 'dspy-ruby_llm' # For 12+ providers via RubyLLM
48
- ```
49
-
50
- ```bash
51
- bundle install
52
- ```
53
-
54
- ## Quick Start
55
-
56
- ### Configure Your LLM
57
-
58
- ```ruby
59
- # OpenAI
60
- DSPy.configure do |c|
61
- c.lm = DSPy::LM.new('openai/gpt-4o-mini',
62
- api_key: ENV['OPENAI_API_KEY'],
63
- structured_outputs: true)
64
- end
65
-
66
- # Anthropic Claude
67
- DSPy.configure do |c|
68
- c.lm = DSPy::LM.new('anthropic/claude-sonnet-4-20250514',
69
- api_key: ENV['ANTHROPIC_API_KEY'])
70
- end
71
-
72
- # Google Gemini
73
- DSPy.configure do |c|
74
- c.lm = DSPy::LM.new('gemini/gemini-2.5-flash',
75
- api_key: ENV['GEMINI_API_KEY'])
76
- end
77
-
78
- # Ollama (local, free)
79
- DSPy.configure do |c|
80
- c.lm = DSPy::LM.new('ollama/llama3.2')
81
- end
82
-
83
- # OpenRouter (200+ models)
84
- DSPy.configure do |c|
85
- c.lm = DSPy::LM.new('openrouter/deepseek/deepseek-chat-v3.1:free',
86
- api_key: ENV['OPENROUTER_API_KEY'])
87
- end
88
- ```
89
-
90
- ### Define a Signature
13
+ The `1.x` series is the current stable release line.
91
14
 
92
- Signatures are typed contracts for LLM operations. Define inputs, outputs, and let DSPy handle the prompt:
15
+ In a configured application, the task contract and call look like this:
93
16
 
94
17
  ```ruby
95
18
  class Classify < DSPy::Signature
96
- description "Classify sentiment of a given sentence."
97
-
98
19
  class Sentiment < T::Enum
99
20
  enums do
100
21
  Positive = new('positive')
@@ -104,7 +25,7 @@ class Classify < DSPy::Signature
104
25
  end
105
26
 
106
27
  input do
107
- const :sentence, String, description: 'The sentence to analyze'
28
+ const :sentence, String
108
29
  end
109
30
 
110
31
  output do
@@ -114,107 +35,39 @@ class Classify < DSPy::Signature
114
35
  end
115
36
 
116
37
  classifier = DSPy::Predict.new(Classify)
117
- result = classifier.call(sentence: "This book was super fun to read!")
118
-
119
- result.sentiment # => #<Sentiment::Positive>
120
- result.confidence # => 0.92
38
+ result = classifier.call(sentence: "This book was fun to read!")
121
39
  ```
122
40
 
123
- ### Chain of Thought
124
-
125
- For complex reasoning, use `ChainOfThought` to get step-by-step explanations:
126
-
127
- ```ruby
128
- solver = DSPy::ChainOfThought.new(MathProblem)
129
- result = solver.call(problem: "If a train travels 120km in 2 hours, what's its speed?")
130
-
131
- result.reasoning # => "Speed = Distance / Time = 120km / 2h = 60km/h"
132
- result.answer # => "60 km/h"
133
- ```
41
+ Define a typed task contract instead of maintaining an output template. Receive validated Ruby values instead of parsing provider JSON. Handle configuration, transport, and validation errors explicitly.
134
42
 
135
- ### ReAct Agents
136
-
137
- Build agents that use tools to accomplish tasks:
138
-
139
- ```ruby
140
- class SearchTool < DSPy::Tools::Base
141
- tool_name "search"
142
- tool_description "Search for information"
143
-
144
- sig { params(query: String).returns(String) }
145
- def call(query:)
146
- # Your search implementation
147
- "Result 1, Result 2"
148
- end
149
- end
150
-
151
- agent = DSPy::ReAct.new(ResearchTask, tools: [SearchTool.new], max_iterations: 5)
152
- result = agent.call(question: "What's the latest on Ruby 3.4?")
153
- ```
43
+ ## Start Here
154
44
 
155
- ## What's Included
45
+ The [Quick Start](https://oss.vicente.services/dspy.rb/getting-started/quick-start/) is the complete supported path: install the core and provider gems, configure a key, save a program, and run it.
156
46
 
157
- **Core Modules**: Predict, ChainOfThought, ReAct agents, and composable pipelines.
47
+ Use [Installation](https://oss.vicente.services/dspy.rb/getting-started/installation/) to choose a provider. The [package and capability matrix](https://oss.vicente.services/dspy.rb/getting-started/packages/) records exact gem names, require behavior, support labels, and model or SDK boundaries.
158
48
 
159
- **Type Safety**: Sorbet-based runtime validation. Enums, unions, nested structs—all work.
49
+ ## Mental Model
160
50
 
161
- **Multimodal**: Image analysis with `DSPy::Image` for vision-capable models.
51
+ - A `DSPy::Signature` defines the task contract.
52
+ - `DSPy::Predict` and other modules choose an execution strategy.
53
+ - Ordinary Ruby owns fixed sequencing, branching, persistence, permissions, and failure policy.
54
+ - Results cross a runtime validation boundary; validation establishes shape, not factual correctness.
162
55
 
163
- **Observability**: Zero-config Langfuse integration via OpenTelemetry. Non-blocking, production-ready.
164
-
165
- **Optimization**: MIPROv2 (Bayesian optimization) and GEPA (genetic evolution) for prompt tuning.
166
-
167
- **Provider Support**: OpenAI, Anthropic, Gemini, Ollama, and OpenRouter via official SDKs.
168
-
169
- ## Documentation
170
-
171
- **[Full Documentation](https://oss.vicente.services/dspy.rb/)** — Getting started, core concepts, advanced patterns.
172
-
173
- **[llms.txt](https://oss.vicente.services/dspy.rb/llms.txt)** — LLM-friendly reference for AI assistants.
174
-
175
- ### Claude Skill
176
-
177
- A [Claude Skill](https://github.com/vicentereig/dspy-rb-skill) is available to help you build DSPy.rb applications:
178
-
179
- ```bash
180
- # Claude Code — install from the vicentereig/engineering marketplace
181
- claude install-skill vicentereig/engineering --skill dspy-rb
182
- ```
183
-
184
- For Claude.ai Pro/Max, download the [skill ZIP](https://github.com/vicentereig/dspy-rb-skill/archive/refs/heads/main.zip) and upload via Settings > Skills.
185
-
186
- ## Examples
187
-
188
- The [examples/](examples/) directory has runnable code for common patterns:
189
-
190
- - Sentiment classification
191
- - ReAct agents with tools
192
- - Image analysis
193
- - Prompt optimization
194
-
195
- ```bash
196
- bundle exec ruby examples/basic_search_agent.rb
197
- ```
56
+ ### ReAct Agents
198
57
 
199
- ## Optional Gems
58
+ Use `ReAct` when the model needs to choose among typed Ruby tools inside an iteration bound. The application still owns tool authorization, side effects, budgets, and errors. See [Predictors](https://oss.vicente.services/dspy.rb/core-concepts/predictors/) and [Toolsets](https://oss.vicente.services/dspy.rb/core-concepts/toolsets/).
200
59
 
201
- DSPy.rb ships sibling gems for features with heavier dependencies. Add them as needed:
60
+ ## Explore
202
61
 
203
- | Gem | What it does |
204
- | --- | --- |
205
- | `dspy-datasets` | Dataset helpers, Parquet/Polars tooling |
206
- | `dspy-evals` | Evaluation harness with metrics and callbacks |
207
- | `dspy-miprov2` | Bayesian optimization for prompt tuning |
208
- | `dspy-gepa` | Genetic-Pareto prompt evolution |
209
- | `dspy-o11y-langfuse` | Auto-configure Langfuse tracing |
210
- | `dspy-code_act` | Think-Code-Observe agents |
211
- | `dspy-deep_search` | Production DeepSearch with Exa |
62
+ - [Documentation](https://oss.vicente.services/dspy.rb/) — task-oriented guides and reference
63
+ - [Examples](examples/) — repository demos indexed by capability and prerequisites
64
+ - [llms.txt](https://oss.vicente.services/dspy.rb/llms.txt) — generated reference for AI assistants
212
65
 
213
- See [the full list](https://oss.vicente.services/dspy.rb/getting-started/installation/) in the docs.
66
+ Provider adapters, optimizers, observability exporters, datasets, and code-executing agents are separate packages when they add dependencies. Check the package matrix before selecting one; package availability does not guarantee uniform provider or model behavior.
214
67
 
215
68
  ## Contributing
216
69
 
217
- Feedback is invaluable. If you encounter issues, [open an issue](https://github.com/vicentereig/dspy.rb/issues). For suggestions, [start a discussion](https://github.com/vicentereig/dspy.rb/discussions).
70
+ For bugs, [open an issue](https://github.com/vicentereig/dspy.rb/issues). For suggestions, [start a discussion](https://github.com/vicentereig/dspy.rb/discussions).
218
71
 
219
72
  Want to contribute code? Reach out: hey at vicente.services
220
73
 
@@ -1,37 +1,52 @@
1
- # DSPy Gemini adapter gem
1
+ # DSPy Gemini Adapter
2
2
 
3
- `dspy-gemini` provides the Gemini adapter for DSPy.rb so we can rely on Google's API without bloating the core gem. Install it whenever you plan to call `gemini/*` model ids from DSPy.
3
+ `dspy-gemini` lets `DSPy::LM` call model IDs with the `gemini/` prefix. The package is a supported provider adapter; model and SDK capabilities still vary.
4
4
 
5
- ## When you need it
6
- - You call `DSPy::LM.new` with a provider of `gemini`.
7
- - You want structured outputs, multimodal prompts, or streaming responses backed by Gemini's Generative Language API.
5
+ See the [package and capability matrix](https://oss.vicente.services/dspy.rb/getting-started/packages/) for canonical status and model/SDK boundaries.
8
6
 
9
- Projects that only target OpenAI, Anthropic, or other providers can skip this gem.
7
+ ## Prerequisites
10
8
 
11
- ## Installation
12
- Add it beside `dspy` and install dependencies:
9
+ - Ruby 3.3 or newer and Bundler
10
+ - a Gemini API key
11
+ - a Gemini model ID available to your account
13
12
 
14
- ```ruby
15
- # Gemfile
16
- gem 'dspy'
17
- gem 'dspy-gemini'
18
- ```
13
+ ## Install and Run
19
14
 
20
- ```sh
21
- bundle install
15
+ Add both gems to your `Gemfile`:
16
+
17
+ ```ruby
18
+ gem "dspy"
19
+ gem "dspy-gemini"
22
20
  ```
23
21
 
24
- The adapter enforces `gemini-ai ~> 4.3` at runtime (and raises if the dependency is missing or out of range).
22
+ Save this as `gemini_smoke.rb`:
25
23
 
26
- ## Configuration
27
- - Set `ENV['GEMINI_API_KEY']`, or pass `api_key:` directly.
24
+ ```ruby
25
+ require "dspy"
28
26
 
29
- ## Basic usage
27
+ lm = DSPy::LM.new(
28
+ ENV.fetch("GEMINI_MODEL"),
29
+ api_key: ENV.fetch("GEMINI_API_KEY")
30
+ )
30
31
 
31
- ```ruby
32
- require 'dspy'
33
- # No need to explicitly require 'dspy/gemini'
32
+ response = lm.raw_chat([{ role: "user", content: "Reply with: adapter ready" }])
33
+ puts response.content
34
+ ```
34
35
 
35
- lm = DSPy::LM.new('gemini/gemini-1.5-flash', api_key: ENV.fetch('GEMINI_API_KEY'))
36
+ Then install and run it:
36
37
 
38
+ ```bash
39
+ bundle install
40
+ export GEMINI_API_KEY="your-key"
41
+ export GEMINI_MODEL="gemini/your-model-id"
42
+ bundle exec ruby gemini_smoke.rb
37
43
  ```
44
+
45
+ The command prints the model response. Requiring `dspy` loads the installed adapter for a `gemini/` model; explicit `require "dspy/gemini"` is also supported.
46
+
47
+ ## Failure Conditions
48
+
49
+ - A missing key raises from `ENV.fetch` before the request.
50
+ - A missing or incompatible `gemini-ai` dependency prevents the adapter from loading.
51
+ - An unavailable model, safety rejection, or invalid request raises an adapter/provider error.
52
+ - Schema, image, safety, and streaming behavior depend on the selected Gemini model and SDK/API version. Verify the exact request; installing the gem does not guarantee every capability.
@@ -5,9 +5,6 @@ require 'json'
5
5
  require 'dspy/lm/vision_models'
6
6
  require 'dspy/lm/adapter'
7
7
 
8
- require 'dspy/gemini/guardrails'
9
- DSPy::Gemini::Guardrails.ensure_gemini_installed!
10
-
11
8
  module DSPy
12
9
  module Gemini
13
10
  module LM
@@ -52,7 +49,9 @@ module DSPy
52
49
  # Validate vision support if images are present
53
50
  if contains_images?(normalized_messages)
54
51
  DSPy::LM::VisionModels.validate_vision_support!('gemini', model)
55
- # Convert messages to Gemini format with proper image handling
52
+ end
53
+
54
+ if contains_media?(normalized_messages)
56
55
  normalized_messages = format_multimodal_messages(normalized_messages, 'gemini')
57
56
  end
58
57
 
@@ -45,8 +45,8 @@ module DSPy
45
45
  # Get the output JSON schema from the signature class
46
46
  output_schema = signature_class.output_json_schema
47
47
 
48
- # Convert to Gemini format (OpenAPI 3.0 Schema subset - not related to OpenAI)
49
- convert_dspy_schema_to_gemini(output_schema)
48
+ # response_json_schema accepts JSON Schema, including nullable type arrays.
49
+ convert_property_to_gemini(output_schema)
50
50
  end
51
51
 
52
52
  sig { params(model: String).returns(T::Boolean) }
@@ -73,87 +73,34 @@ module DSPy
73
73
 
74
74
  private
75
75
 
76
- sig { params(dspy_schema: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
77
- def self.convert_dspy_schema_to_gemini(dspy_schema)
78
- # For Gemini's responseJsonSchema, we need pure JSON Schema format
79
- # Remove OpenAPI-specific fields like "$schema"
80
- result = {
81
- type: "object",
82
- properties: {},
83
- required: []
84
- }
85
-
86
- # Convert properties
87
- properties = dspy_schema[:properties] || {}
88
- properties.each do |prop_name, prop_schema|
89
- result[:properties][prop_name] = convert_property_to_gemini(prop_schema)
90
- end
91
-
92
- # Set required fields
93
- result[:required] = (dspy_schema[:required] || []).map(&:to_s)
94
-
95
- result
96
- end
97
-
98
76
  sig { params(property_schema: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
99
77
  def self.convert_property_to_gemini(property_schema)
100
- # Handle oneOf/anyOf schemas (union types) - Gemini supports these in responseJsonSchema
101
- if property_schema[:oneOf]
102
- return {
103
- oneOf: property_schema[:oneOf].map { |schema| convert_property_to_gemini(schema) },
104
- description: property_schema[:description]
105
- }.compact
106
- end
78
+ # Preserve types and constraints instead of rebuilding nodes from scalar
79
+ # type names: Sorbet represents nilable fields as type: [type, "null"].
80
+ result = property_schema.reject { |key, _| key == :"$schema" || key == :const }
107
81
 
108
- if property_schema[:anyOf]
109
- return {
110
- anyOf: property_schema[:anyOf].map { |schema| convert_property_to_gemini(schema) },
111
- description: property_schema[:description]
112
- }.compact
113
- end
82
+ # Keep the existing const-to-enum conversion, including false/null values.
83
+ result[:enum] = [property_schema[:const]] if property_schema.key?(:const)
114
84
 
115
- case property_schema[:type]
116
- when "string"
117
- result = { type: "string" }
118
- # Gemini responseJsonSchema doesn't support const, so convert to single-value enum
119
- # See: https://ai.google.dev/api/generate-content#FIELDS.response_json_schema
120
- if property_schema[:const]
121
- result[:enum] = [property_schema[:const]]
122
- elsif property_schema[:enum]
123
- result[:enum] = property_schema[:enum]
85
+ [:properties, :"$defs", :definitions].each do |key|
86
+ if property_schema[key].is_a?(Hash)
87
+ result[key] = property_schema[key].transform_values { |schema| convert_property_to_gemini(schema) }
124
88
  end
125
- result
126
- when "integer"
127
- { type: "integer" }
128
- when "number"
129
- { type: "number" }
130
- when "boolean"
131
- { type: "boolean" }
132
- when "array"
133
- {
134
- type: "array",
135
- items: convert_property_to_gemini(property_schema[:items] || { type: "string" })
136
- }
137
- when "object"
138
- result = { type: "object" }
139
-
140
- if property_schema[:properties]
141
- result[:properties] = {}
142
- property_schema[:properties].each do |nested_prop, nested_schema|
143
- result[:properties][nested_prop] = convert_property_to_gemini(nested_schema)
144
- end
89
+ end
145
90
 
146
- # Set required fields for nested objects
147
- if property_schema[:required]
148
- result[:required] = property_schema[:required].map(&:to_s)
149
- end
91
+ [:items, :additionalProperties].each do |key|
92
+ if property_schema[key].is_a?(Hash)
93
+ result[key] = convert_property_to_gemini(property_schema[key])
150
94
  end
95
+ end
151
96
 
152
- result
153
- else
154
- # Default to string for unknown types
155
- { type: "string" }
97
+ [:oneOf, :anyOf, :allOf, :prefixItems].each do |key|
98
+ if property_schema[key].is_a?(Array)
99
+ result[key] = property_schema[key].map { |schema| convert_property_to_gemini(schema) }
100
+ end
156
101
  end
102
+
103
+ result
157
104
  end
158
105
 
159
106
  sig { params(schema: T::Hash[Symbol, T.untyped], current_depth: Integer).returns(Integer) }
@@ -2,6 +2,6 @@
2
2
 
3
3
  module DSPy
4
4
  module Gemini
5
- VERSION = '1.0.3'
5
+ VERSION = '1.0.5'
6
6
  end
7
7
  end
data/lib/dspy/gemini.rb CHANGED
@@ -2,8 +2,5 @@
2
2
 
3
3
  require 'dspy/gemini/version'
4
4
 
5
- require 'dspy/gemini/guardrails'
6
- DSPy::Gemini::Guardrails.ensure_gemini_installed!
7
-
8
5
  require 'dspy/gemini/lm/adapters/gemini_adapter'
9
6
  require 'dspy/gemini/lm/schema_converter'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dspy-gemini
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vicente Reig Rincón de Arellano
@@ -15,28 +15,40 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0.30'
18
+ version: 0.30.1
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '2.0'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
26
  - - ">="
24
27
  - !ruby/object:Gem::Version
25
- version: '0.30'
28
+ version: 0.30.1
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '2.0'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: gemini-ai
28
34
  requirement: !ruby/object:Gem::Requirement
29
35
  requirements:
30
36
  - - ">="
31
37
  - !ruby/object:Gem::Version
32
- version: '0'
38
+ version: 4.3.0
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '5.0'
33
42
  type: :runtime
34
43
  prerelease: false
35
44
  version_requirements: !ruby/object:Gem::Requirement
36
45
  requirements:
37
46
  - - ">="
38
47
  - !ruby/object:Gem::Version
39
- version: '0'
48
+ version: 4.3.0
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '5.0'
40
52
  description: Provides the GeminiAdapter so Gemini-compatible providers can be added
41
53
  to DSPy.rb projects independently of the core gem.
42
54
  email:
@@ -49,7 +61,6 @@ files:
49
61
  - README.md
50
62
  - lib/dspy/gemini.rb
51
63
  - lib/dspy/gemini/README.md
52
- - lib/dspy/gemini/guardrails.rb
53
64
  - lib/dspy/gemini/lm/adapters/gemini_adapter.rb
54
65
  - lib/dspy/gemini/lm/schema_converter.rb
55
66
  - lib/dspy/gemini/version.rb
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dspy/lm/errors'
4
-
5
- module DSPy
6
- module Gemini
7
- class Guardrails
8
- SUPPORTED_GEMINI_VERSIONS = "~> 4.3".freeze
9
-
10
- def self.ensure_gemini_installed!
11
- require 'gemini-ai'
12
-
13
- spec = Gem.loaded_specs["gemini-ai"]
14
- unless spec && Gem::Requirement.new(SUPPORTED_GEMINI_VERSIONS).satisfied_by?(spec.version)
15
- msg = <<~MSG
16
- DSPY requires `gemini-ai` gem #{SUPPORTED_GEMINI_VERSIONS}.
17
- Please Install or upgrade it with `bundle add gemini-ai --version "#{SUPPORTED_GEMINI_VERSIONS}"`.
18
- MSG
19
- raise DSPy::LM::UnsupportedVersionError, msg
20
- end
21
- end
22
- end
23
- end
24
- end
25
-