desiru 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/.env.example +34 -0
- data/.rubocop.yml +7 -4
- data/.ruby-version +1 -0
- data/CLAUDE.md +4 -0
- data/Gemfile +21 -2
- data/Gemfile.lock +87 -12
- data/README.md +295 -2
- data/Rakefile +1 -0
- data/db/migrations/001_create_initial_tables.rb +96 -0
- data/db/migrations/002_create_job_results.rb +39 -0
- data/desiru.db +0 -0
- data/desiru.gemspec +2 -5
- data/docs/background_processing_roadmap.md +87 -0
- data/docs/job_scheduling.md +167 -0
- data/dspy-analysis-swarm.yml +60 -0
- data/dspy-feature-analysis.md +121 -0
- data/examples/README.md +69 -0
- data/examples/api_with_persistence.rb +122 -0
- data/examples/assertions_example.rb +232 -0
- data/examples/async_processing.rb +2 -0
- data/examples/few_shot_learning.rb +1 -2
- data/examples/graphql_api.rb +4 -2
- data/examples/graphql_integration.rb +3 -3
- data/examples/graphql_optimization_summary.md +143 -0
- data/examples/graphql_performance_benchmark.rb +247 -0
- data/examples/persistence_example.rb +102 -0
- data/examples/react_agent.rb +203 -0
- data/examples/rest_api.rb +173 -0
- data/examples/rest_api_advanced.rb +333 -0
- data/examples/scheduled_job_example.rb +116 -0
- data/examples/simple_qa.rb +1 -2
- data/examples/sinatra_api.rb +109 -0
- data/examples/typed_signatures.rb +1 -2
- data/graphql_optimization_summary.md +53 -0
- data/lib/desiru/api/grape_integration.rb +284 -0
- data/lib/desiru/api/persistence_middleware.rb +148 -0
- data/lib/desiru/api/sinatra_integration.rb +217 -0
- data/lib/desiru/api.rb +42 -0
- data/lib/desiru/assertions.rb +74 -0
- data/lib/desiru/async_status.rb +65 -0
- data/lib/desiru/cache.rb +1 -1
- data/lib/desiru/configuration.rb +2 -1
- data/lib/desiru/errors.rb +160 -0
- data/lib/desiru/field.rb +17 -14
- data/lib/desiru/graphql/batch_loader.rb +85 -0
- data/lib/desiru/graphql/data_loader.rb +242 -75
- data/lib/desiru/graphql/enum_builder.rb +75 -0
- data/lib/desiru/graphql/executor.rb +37 -4
- data/lib/desiru/graphql/schema_generator.rb +62 -158
- data/lib/desiru/graphql/type_builder.rb +138 -0
- data/lib/desiru/graphql/type_cache_warmer.rb +91 -0
- data/lib/desiru/jobs/async_predict.rb +1 -1
- data/lib/desiru/jobs/base.rb +67 -0
- data/lib/desiru/jobs/batch_processor.rb +6 -6
- data/lib/desiru/jobs/retriable.rb +119 -0
- data/lib/desiru/jobs/retry_strategies.rb +169 -0
- data/lib/desiru/jobs/scheduler.rb +219 -0
- data/lib/desiru/jobs/webhook_notifier.rb +242 -0
- data/lib/desiru/models/anthropic.rb +164 -0
- data/lib/desiru/models/base.rb +37 -3
- data/lib/desiru/models/open_ai.rb +151 -0
- data/lib/desiru/models/open_router.rb +161 -0
- data/lib/desiru/module.rb +59 -9
- data/lib/desiru/modules/chain_of_thought.rb +3 -3
- data/lib/desiru/modules/majority.rb +51 -0
- data/lib/desiru/modules/multi_chain_comparison.rb +204 -0
- data/lib/desiru/modules/predict.rb +8 -1
- data/lib/desiru/modules/program_of_thought.rb +139 -0
- data/lib/desiru/modules/react.rb +273 -0
- data/lib/desiru/modules/retrieve.rb +4 -2
- data/lib/desiru/optimizers/base.rb +2 -4
- data/lib/desiru/optimizers/bootstrap_few_shot.rb +2 -2
- data/lib/desiru/optimizers/copro.rb +268 -0
- data/lib/desiru/optimizers/knn_few_shot.rb +185 -0
- data/lib/desiru/persistence/database.rb +71 -0
- data/lib/desiru/persistence/models/api_request.rb +38 -0
- data/lib/desiru/persistence/models/job_result.rb +138 -0
- data/lib/desiru/persistence/models/module_execution.rb +37 -0
- data/lib/desiru/persistence/models/optimization_result.rb +28 -0
- data/lib/desiru/persistence/models/training_example.rb +25 -0
- data/lib/desiru/persistence/models.rb +11 -0
- data/lib/desiru/persistence/repositories/api_request_repository.rb +98 -0
- data/lib/desiru/persistence/repositories/base_repository.rb +77 -0
- data/lib/desiru/persistence/repositories/job_result_repository.rb +116 -0
- data/lib/desiru/persistence/repositories/module_execution_repository.rb +85 -0
- data/lib/desiru/persistence/repositories/optimization_result_repository.rb +67 -0
- data/lib/desiru/persistence/repositories/training_example_repository.rb +102 -0
- data/lib/desiru/persistence/repository.rb +29 -0
- data/lib/desiru/persistence/setup.rb +77 -0
- data/lib/desiru/persistence.rb +49 -0
- data/lib/desiru/registry.rb +3 -5
- data/lib/desiru/signature.rb +91 -24
- data/lib/desiru/version.rb +1 -1
- data/lib/desiru.rb +23 -8
- data/missing-features-analysis.md +192 -0
- metadata +63 -45
- data/lib/desiru/models/raix_adapter.rb +0 -210
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
|
5
|
+
module Desiru
|
6
|
+
module Persistence
|
7
|
+
# Setup and initialization for persistence layer
|
8
|
+
module Setup
|
9
|
+
@initialized = false
|
10
|
+
|
11
|
+
def self.initialized?
|
12
|
+
@initialized
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.initialize!(db_connection)
|
16
|
+
# Always reinitialize if the database connection has changed
|
17
|
+
return if @initialized && Sequel::Model.db == db_connection
|
18
|
+
|
19
|
+
# Ensure we have a valid connection
|
20
|
+
raise 'Database connection required' unless db_connection
|
21
|
+
|
22
|
+
# Create the base model with a specific database
|
23
|
+
Sequel::Model.db = db_connection
|
24
|
+
|
25
|
+
# Define the base model class
|
26
|
+
base_class = Class.new(Sequel::Model) do
|
27
|
+
# This is an abstract model - no table
|
28
|
+
def self.inherited(subclass)
|
29
|
+
super
|
30
|
+
subclass.plugin :timestamps, update_on_create: true
|
31
|
+
subclass.plugin :json_serializer
|
32
|
+
subclass.plugin :validation_helpers
|
33
|
+
end
|
34
|
+
|
35
|
+
# Helper to create JSON columns that work across databases
|
36
|
+
def self.json_column(name)
|
37
|
+
case db.adapter_scheme
|
38
|
+
when :postgres
|
39
|
+
# PostgreSQL has native JSON support
|
40
|
+
nil # No special handling needed
|
41
|
+
when :sqlite, :mysql, :mysql2
|
42
|
+
# SQLite and MySQL store JSON as text
|
43
|
+
plugin :serialization
|
44
|
+
serialize_attributes :json, name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Make it unrestricted so it doesn't look for a table
|
50
|
+
base_class.unrestrict_primary_key
|
51
|
+
|
52
|
+
# Set the Base constant
|
53
|
+
Models.send(:remove_const, :Base) if Models.const_defined?(:Base)
|
54
|
+
Models.const_set(:Base, base_class)
|
55
|
+
|
56
|
+
# Remove existing model constants to force reload
|
57
|
+
%i[ModuleExecution ApiRequest OptimizationResult TrainingExample JobResult].each do |model|
|
58
|
+
Models.send(:remove_const, model) if Models.const_defined?(model)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Now load all model classes - use load instead of require to force re-execution
|
62
|
+
load File.expand_path('models/module_execution.rb', __dir__)
|
63
|
+
load File.expand_path('models/api_request.rb', __dir__)
|
64
|
+
load File.expand_path('models/optimization_result.rb', __dir__)
|
65
|
+
load File.expand_path('models/training_example.rb', __dir__)
|
66
|
+
load File.expand_path('models/job_result.rb', __dir__)
|
67
|
+
|
68
|
+
# Setup repositories
|
69
|
+
require_relative 'repository'
|
70
|
+
Repository.setup!
|
71
|
+
|
72
|
+
@initialized = true
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'persistence/database'
|
4
|
+
require_relative 'persistence/models'
|
5
|
+
require_relative 'persistence/repository'
|
6
|
+
|
7
|
+
module Desiru
|
8
|
+
# Database persistence layer for Desiru
|
9
|
+
module Persistence
|
10
|
+
class << self
|
11
|
+
attr_writer :database_url
|
12
|
+
|
13
|
+
def database_url
|
14
|
+
@database_url ||= ENV['DESIRU_DATABASE_URL'] || 'sqlite://desiru.db'
|
15
|
+
end
|
16
|
+
|
17
|
+
def connect!
|
18
|
+
Database.connect(database_url)
|
19
|
+
end
|
20
|
+
|
21
|
+
def disconnect!
|
22
|
+
Database.disconnect
|
23
|
+
end
|
24
|
+
|
25
|
+
def migrate!
|
26
|
+
Database.migrate!
|
27
|
+
Repository.setup!
|
28
|
+
end
|
29
|
+
|
30
|
+
def repositories
|
31
|
+
@repositories ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def register_repository(name, repository)
|
35
|
+
repositories[name] = repository
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](name)
|
39
|
+
repositories[name] || raise("Repository #{name} not found")
|
40
|
+
end
|
41
|
+
|
42
|
+
def enabled?
|
43
|
+
!Database.connection.nil?
|
44
|
+
rescue StandardError
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/desiru/registry.rb
CHANGED
@@ -32,11 +32,9 @@ module Desiru
|
|
32
32
|
def get(name, version: nil)
|
33
33
|
name = name.to_sym
|
34
34
|
|
35
|
-
if version
|
36
|
-
|
37
|
-
|
38
|
-
@modules[name] || raise(ModuleError, "Module #{name} not found")
|
39
|
-
end
|
35
|
+
return @module_versions[name][version] || raise(ModuleError, "Module #{name} v#{version} not found") if version
|
36
|
+
|
37
|
+
@modules[name] || raise(ModuleError, "Module #{name} not found")
|
40
38
|
end
|
41
39
|
|
42
40
|
def list
|
data/lib/desiru/signature.rb
CHANGED
@@ -4,10 +4,46 @@ module Desiru
|
|
4
4
|
# Represents input/output specifications for modules
|
5
5
|
# Supports DSL-style signature strings like "question -> answer"
|
6
6
|
class Signature
|
7
|
+
# FieldWrapper provides a test-compatible interface for Field objects
|
8
|
+
class FieldWrapper
|
9
|
+
def initialize(field)
|
10
|
+
@field = field
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
@field.type
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
@field.description
|
19
|
+
end
|
20
|
+
|
21
|
+
def optional
|
22
|
+
@field.optional
|
23
|
+
end
|
24
|
+
|
25
|
+
def optional?
|
26
|
+
@field.optional?
|
27
|
+
end
|
28
|
+
|
29
|
+
def name
|
30
|
+
@field.name
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method, *, &)
|
34
|
+
@field.send(method, *, &)
|
35
|
+
end
|
36
|
+
|
37
|
+
def respond_to_missing?(method, include_private = false)
|
38
|
+
@field.respond_to?(method, include_private)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
7
42
|
# FieldHash allows access by both string and symbol keys
|
8
43
|
class FieldHash < Hash
|
9
44
|
def [](key)
|
10
|
-
super(key.to_sym)
|
45
|
+
field = super(key.to_sym)
|
46
|
+
field ? FieldWrapper.new(field) : nil
|
11
47
|
end
|
12
48
|
|
13
49
|
def []=(key, value)
|
@@ -18,12 +54,12 @@ module Desiru
|
|
18
54
|
super.map(&:to_s)
|
19
55
|
end
|
20
56
|
|
21
|
-
def
|
57
|
+
def key?(key)
|
22
58
|
super(key.to_sym)
|
23
59
|
end
|
24
60
|
|
25
|
-
alias include?
|
26
|
-
alias
|
61
|
+
alias include? key?
|
62
|
+
alias has_key? key?
|
27
63
|
end
|
28
64
|
|
29
65
|
attr_reader :raw_signature
|
@@ -51,7 +87,7 @@ module Desiru
|
|
51
87
|
parse_signature!
|
52
88
|
end
|
53
89
|
|
54
|
-
def
|
90
|
+
def valid_inputs?(inputs)
|
55
91
|
missing = required_input_fields - inputs.keys.map(&:to_sym)
|
56
92
|
raise SignatureError, "Missing required inputs: #{missing.join(', ')}" if missing.any?
|
57
93
|
|
@@ -60,13 +96,13 @@ module Desiru
|
|
60
96
|
next unless field
|
61
97
|
|
62
98
|
# Field.validate will raise ValidationError if validation fails
|
63
|
-
field.
|
99
|
+
field.valid?(value)
|
64
100
|
end
|
65
101
|
|
66
102
|
true
|
67
103
|
end
|
68
104
|
|
69
|
-
def
|
105
|
+
def valid_outputs?(outputs)
|
70
106
|
missing = required_output_fields - outputs.keys.map(&:to_sym)
|
71
107
|
raise ValidationError, "Missing required outputs: #{missing.join(', ')}" if missing.any?
|
72
108
|
|
@@ -75,7 +111,7 @@ module Desiru
|
|
75
111
|
next unless field
|
76
112
|
|
77
113
|
# Field.validate will raise ValidationError if validation fails
|
78
|
-
field.
|
114
|
+
field.valid?(value)
|
79
115
|
end
|
80
116
|
|
81
117
|
true
|
@@ -138,7 +174,7 @@ module Desiru
|
|
138
174
|
bracket_count += 1
|
139
175
|
elsif char == ']'
|
140
176
|
bracket_count -= 1
|
141
|
-
elsif char == ',' && bracket_count
|
177
|
+
elsif char == ',' && bracket_count.zero?
|
142
178
|
fields << current_field.strip
|
143
179
|
current_field = String.new
|
144
180
|
next
|
@@ -155,23 +191,37 @@ module Desiru
|
|
155
191
|
optional = name.end_with?('?') || type_info.include?('?')
|
156
192
|
# Clean field name by removing trailing ?
|
157
193
|
name = name.gsub(/\?$/, '')
|
194
|
+
|
195
|
+
# Extract description if present (in quotes at the end)
|
196
|
+
description = nil
|
197
|
+
# Look for description only after the type definition, not within brackets
|
198
|
+
if type_info =~ /^([^"]+?)\s+"([^"]+)"$/
|
199
|
+
type_info = ::Regexp.last_match(1).strip
|
200
|
+
description = ::Regexp.last_match(2)
|
201
|
+
end
|
202
|
+
|
158
203
|
# Remove optional marker before parsing type
|
159
204
|
clean_type_info = type_info.gsub('?', '').strip
|
160
205
|
type_data = parse_type(clean_type_info)
|
206
|
+
# Store the original type string for tests
|
207
|
+
type_data[:original_type] = clean_type_info
|
161
208
|
else
|
162
209
|
name = field_str
|
163
210
|
# Check if field name ends with ?
|
164
211
|
optional = name.end_with?('?')
|
165
212
|
name = name.gsub(/\?$/, '')
|
166
|
-
type_data = { type: :string }
|
213
|
+
type_data = { type: :string, original_type: 'string' }
|
214
|
+
description = nil
|
167
215
|
end
|
168
216
|
|
169
|
-
description
|
217
|
+
# Use extracted description or fallback to descriptions hash
|
218
|
+
description ||= @descriptions[name.to_sym] || @descriptions[name.to_s]
|
170
219
|
|
171
220
|
# Create field with parsed type data
|
172
221
|
field_args = {
|
173
222
|
description: description,
|
174
|
-
optional: optional
|
223
|
+
optional: optional,
|
224
|
+
original_type: type_data[:original_type]
|
175
225
|
}
|
176
226
|
|
177
227
|
# Add literal values if present
|
@@ -209,17 +259,17 @@ module Desiru
|
|
209
259
|
bracket_count += 1
|
210
260
|
elsif char == ']'
|
211
261
|
bracket_count -= 1
|
212
|
-
if bracket_count
|
262
|
+
if bracket_count.zero?
|
213
263
|
end_index = index
|
214
264
|
break
|
215
265
|
end
|
216
266
|
end
|
217
267
|
end
|
218
268
|
|
219
|
-
if end_index
|
269
|
+
if end_index.positive?
|
220
270
|
literal_content = type_string[8...end_index] # Extract content between 'Literal[' and ']'
|
221
271
|
values = parse_literal_values(literal_content)
|
222
|
-
return { type: :literal, literal_values: values }
|
272
|
+
return { type: :literal, literal_values: values, original_type: type_string }
|
223
273
|
end
|
224
274
|
end
|
225
275
|
|
@@ -237,33 +287,36 @@ module Desiru
|
|
237
287
|
bracket_count += 1
|
238
288
|
elsif char == ']'
|
239
289
|
bracket_count -= 1
|
240
|
-
if bracket_count
|
290
|
+
if bracket_count.zero?
|
241
291
|
end_index = index
|
242
292
|
break
|
243
293
|
end
|
244
294
|
end
|
245
295
|
end
|
246
296
|
|
247
|
-
if end_index
|
297
|
+
if end_index.positive?
|
248
298
|
element_type_str = type_string[(start_index + 1)...end_index]
|
249
299
|
element_type_data = parse_type(element_type_str) # Recursive for nested types
|
250
|
-
return { type: :list, element_type: element_type_data }
|
300
|
+
return { type: :list, element_type: element_type_data, original_type: type_string }
|
251
301
|
end
|
252
302
|
end
|
253
303
|
|
254
304
|
# Handle Union types (for future implementation)
|
255
305
|
if type_string.start_with?('Union[')
|
256
306
|
# Placeholder for union type parsing
|
257
|
-
return { type: :union, union_types: [] } # To be implemented
|
307
|
+
return { type: :union, union_types: [], original_type: type_string } # To be implemented
|
258
308
|
end
|
259
309
|
|
260
310
|
# Handle basic types
|
261
311
|
# First check if it's a list/array with simple element type (e.g., list[str])
|
262
312
|
if type_string.downcase.start_with?('list[', 'array[')
|
263
313
|
# Even if we couldn't parse the brackets properly above, it's still a list
|
264
|
-
return { type: :list }
|
314
|
+
return { type: :list, original_type: type_string }
|
265
315
|
end
|
266
316
|
|
317
|
+
# Handle dict/dictionary types with special parsing
|
318
|
+
return { type: :hash, original_type: type_string } if type_string.downcase.start_with?('dict[', 'dictionary[')
|
319
|
+
|
267
320
|
clean_type = type_string.gsub(/[?\[\]]/, '').downcase
|
268
321
|
type_sym = case clean_type
|
269
322
|
when 'str', 'string' then :string
|
@@ -275,7 +328,7 @@ module Desiru
|
|
275
328
|
else clean_type.to_sym
|
276
329
|
end
|
277
330
|
|
278
|
-
{ type: type_sym }
|
331
|
+
{ type: type_sym, original_type: type_string }
|
279
332
|
end
|
280
333
|
|
281
334
|
def parse_literal_values(literal_content)
|
@@ -289,16 +342,23 @@ module Desiru
|
|
289
342
|
if !in_quotes && ['"', "'"].include?(char)
|
290
343
|
in_quotes = true
|
291
344
|
quote_char = char
|
345
|
+
current_value << char # Include the quote in the value
|
292
346
|
elsif in_quotes && char == quote_char
|
293
347
|
# Check if it's escaped
|
294
|
-
if index
|
348
|
+
if index.positive? && literal_content[index - 1] != '\\'
|
295
349
|
in_quotes = false
|
350
|
+
current_value << char # Include the closing quote
|
296
351
|
quote_char = nil
|
297
352
|
else
|
298
353
|
current_value << char
|
299
354
|
end
|
300
355
|
elsif !in_quotes && char == ','
|
301
|
-
|
356
|
+
val = current_value.strip
|
357
|
+
# Remove outer quotes if present
|
358
|
+
if (val.start_with?('"') && val.end_with?('"')) || (val.start_with?("'") && val.end_with?("'"))
|
359
|
+
val = val[1...-1]
|
360
|
+
end
|
361
|
+
values << val
|
302
362
|
current_value = String.new
|
303
363
|
else
|
304
364
|
current_value << char
|
@@ -306,7 +366,14 @@ module Desiru
|
|
306
366
|
end
|
307
367
|
|
308
368
|
# Add the last value
|
309
|
-
|
369
|
+
unless current_value.empty?
|
370
|
+
val = current_value.strip
|
371
|
+
# Remove outer quotes if present
|
372
|
+
if (val.start_with?('"') && val.end_with?('"')) || (val.start_with?("'") && val.end_with?("'"))
|
373
|
+
val = val[1...-1]
|
374
|
+
end
|
375
|
+
values << val
|
376
|
+
end
|
310
377
|
|
311
378
|
values
|
312
379
|
end
|
data/lib/desiru/version.rb
CHANGED
data/lib/desiru.rb
CHANGED
@@ -5,13 +5,6 @@ require 'singleton'
|
|
5
5
|
|
6
6
|
# Main namespace for Desiru - Declarative Self-Improving Ruby
|
7
7
|
module Desiru
|
8
|
-
class Error < StandardError; end
|
9
|
-
class ConfigurationError < Error; end
|
10
|
-
class SignatureError < Error; end
|
11
|
-
class ModuleError < Error; end
|
12
|
-
class ValidationError < Error; end
|
13
|
-
class TimeoutError < Error; end
|
14
|
-
|
15
8
|
class << self
|
16
9
|
attr_writer :configuration
|
17
10
|
|
@@ -26,14 +19,20 @@ module Desiru
|
|
26
19
|
def reset_configuration!
|
27
20
|
@configuration = Configuration.new
|
28
21
|
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
configuration.logger
|
25
|
+
end
|
29
26
|
end
|
30
27
|
end
|
31
28
|
|
32
29
|
# Core components
|
33
30
|
require_relative 'desiru/version'
|
31
|
+
require_relative 'desiru/errors'
|
34
32
|
require_relative 'desiru/configuration'
|
35
33
|
require_relative 'desiru/field'
|
36
34
|
require_relative 'desiru/signature'
|
35
|
+
require_relative 'desiru/assertions'
|
37
36
|
require_relative 'desiru/module'
|
38
37
|
require_relative 'desiru/program'
|
39
38
|
require_relative 'desiru/registry'
|
@@ -41,23 +40,39 @@ require_relative 'desiru/cache'
|
|
41
40
|
|
42
41
|
# Model adapters
|
43
42
|
require_relative 'desiru/models/base'
|
44
|
-
require_relative 'desiru/models/
|
43
|
+
require_relative 'desiru/models/anthropic'
|
44
|
+
require_relative 'desiru/models/open_ai'
|
45
|
+
require_relative 'desiru/models/open_router'
|
45
46
|
|
46
47
|
# Built-in modules
|
47
48
|
require_relative 'desiru/modules/predict'
|
48
49
|
require_relative 'desiru/modules/chain_of_thought'
|
49
50
|
require_relative 'desiru/modules/retrieve'
|
51
|
+
require_relative 'desiru/modules/react'
|
52
|
+
require_relative 'desiru/modules/program_of_thought'
|
53
|
+
require_relative 'desiru/modules/multi_chain_comparison'
|
54
|
+
require_relative 'desiru/modules/majority'
|
50
55
|
|
51
56
|
# Optimizers
|
52
57
|
require_relative 'desiru/optimizers/base'
|
53
58
|
require_relative 'desiru/optimizers/bootstrap_few_shot'
|
59
|
+
require_relative 'desiru/optimizers/knn_few_shot'
|
60
|
+
require_relative 'desiru/optimizers/copro'
|
54
61
|
|
55
62
|
# Background jobs
|
63
|
+
require_relative 'desiru/async_capable'
|
64
|
+
require_relative 'desiru/async_status'
|
56
65
|
require_relative 'desiru/jobs/base'
|
57
66
|
require_relative 'desiru/jobs/async_predict'
|
58
67
|
require_relative 'desiru/jobs/batch_processor'
|
68
|
+
|
69
|
+
# API integrations
|
70
|
+
require_relative 'desiru/api'
|
59
71
|
require_relative 'desiru/jobs/optimizer_job'
|
60
72
|
|
73
|
+
# Persistence layer
|
74
|
+
require_relative 'desiru/persistence'
|
75
|
+
|
61
76
|
# GraphQL integration (optional, requires 'graphql' gem)
|
62
77
|
begin
|
63
78
|
require 'graphql'
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# Missing DSPy Features in Desiru
|
2
|
+
|
3
|
+
Based on analysis of Python DSPy vs current Desiru implementation.
|
4
|
+
|
5
|
+
## Missing Modules
|
6
|
+
|
7
|
+
### 1. **ProgramOfThought**
|
8
|
+
- Generates executable code instead of natural language
|
9
|
+
- Critical for math/logic problems requiring computation
|
10
|
+
- Uses code execution environment
|
11
|
+
|
12
|
+
### 2. **MultiChainComparison**
|
13
|
+
- Runs multiple ChainOfThought instances
|
14
|
+
- Compares and selects best reasoning path
|
15
|
+
- Useful for complex reasoning tasks
|
16
|
+
|
17
|
+
### 3. **BestOfN**
|
18
|
+
- Samples N outputs from any module
|
19
|
+
- Selects best based on metric/scoring
|
20
|
+
- Simple but effective ensemble technique
|
21
|
+
|
22
|
+
### 4. **Refine**
|
23
|
+
- Iterative refinement of outputs
|
24
|
+
- Takes initial output and improves it
|
25
|
+
- Works with constraints and feedback
|
26
|
+
|
27
|
+
### 5. **ChainOfThoughtWithHint**
|
28
|
+
- ChainOfThought variant with guided hints
|
29
|
+
- Provides additional context for reasoning
|
30
|
+
- Better control over reasoning direction
|
31
|
+
|
32
|
+
## Missing Optimizers
|
33
|
+
|
34
|
+
### 1. **MIPROv2**
|
35
|
+
- Most advanced DSPy optimizer
|
36
|
+
- Uses Bayesian optimization
|
37
|
+
- Optimizes both instructions and demonstrations
|
38
|
+
- Significantly better than BootstrapFewShot
|
39
|
+
|
40
|
+
### 2. **COPRO (Collaborative Prompt Optimization)**
|
41
|
+
- Coordinates multiple optimization strategies
|
42
|
+
- Collaborative approach to prompt engineering
|
43
|
+
- Handles complex multi-module programs
|
44
|
+
|
45
|
+
### 3. **BootstrapFewShotWithRandomSearch**
|
46
|
+
- Enhanced version of BootstrapFewShot
|
47
|
+
- Adds hyperparameter random search
|
48
|
+
- Better exploration of optimization space
|
49
|
+
|
50
|
+
### 4. **LabeledFewShot**
|
51
|
+
- Simple optimizer using provided examples
|
52
|
+
- No bootstrapping, just uses given labels
|
53
|
+
- Good baseline optimizer
|
54
|
+
|
55
|
+
### 5. **KNNFewShot**
|
56
|
+
- K-nearest neighbor example selection
|
57
|
+
- Dynamic example selection based on input
|
58
|
+
- Better than static few-shot examples
|
59
|
+
|
60
|
+
### 6. **BootstrapFinetune**
|
61
|
+
- Generates training data for model finetuning
|
62
|
+
- Alternative to prompt optimization
|
63
|
+
- For when you can modify the model
|
64
|
+
|
65
|
+
### 7. **Ensemble**
|
66
|
+
- Combines multiple optimized programs
|
67
|
+
- Voting or weighted combination
|
68
|
+
- Improved robustness
|
69
|
+
|
70
|
+
### 8. **SignatureOptimizer**
|
71
|
+
- Optimizes signature descriptions themselves
|
72
|
+
- Rewrites field descriptions for clarity
|
73
|
+
- Meta-optimization approach
|
74
|
+
|
75
|
+
### 9. **BayesianSignatureOptimizer**
|
76
|
+
- Bayesian approach to signature optimization
|
77
|
+
- More sophisticated than SignatureOptimizer
|
78
|
+
- Better exploration of description space
|
79
|
+
|
80
|
+
## Missing Core Features
|
81
|
+
|
82
|
+
### 1. **Example and Prediction Classes**
|
83
|
+
- Special data containers with utilities
|
84
|
+
- Flexible field access (dot notation)
|
85
|
+
- Completion tracking for Predictions
|
86
|
+
- Integration with trace system
|
87
|
+
|
88
|
+
### 2. **Typed Predictors**
|
89
|
+
- Type-safe field handling
|
90
|
+
- Pydantic integration in Python
|
91
|
+
- Automatic validation and parsing
|
92
|
+
- Better IDE support
|
93
|
+
|
94
|
+
### 3. **Suggestions (Soft Constraints)**
|
95
|
+
- Unlike Assertions (hard constraints)
|
96
|
+
- Guide optimization without failing
|
97
|
+
- Used during compilation phase
|
98
|
+
|
99
|
+
### 4. **Trace Collection System**
|
100
|
+
- Detailed execution tracking
|
101
|
+
- Records all LLM calls and transformations
|
102
|
+
- Critical for optimization
|
103
|
+
- Enables debugging and analysis
|
104
|
+
|
105
|
+
### 5. **Compilation Infrastructure**
|
106
|
+
- Full compilation pipeline
|
107
|
+
- Trace filtering and selection
|
108
|
+
- Demonstration ranking
|
109
|
+
- Parameter update mechanism
|
110
|
+
|
111
|
+
### 6. **Instruction Generation**
|
112
|
+
- Some optimizers generate custom instructions
|
113
|
+
- Not just examples but rewritten prompts
|
114
|
+
- Adaptive to task requirements
|
115
|
+
|
116
|
+
## Missing Utilities & Capabilities
|
117
|
+
|
118
|
+
### 1. **Data Loaders**
|
119
|
+
- HuggingFace dataset integration
|
120
|
+
- CSV/JSON loaders with DSPy formatting
|
121
|
+
- Train/dev/test split utilities
|
122
|
+
- Batch processing support
|
123
|
+
|
124
|
+
### 2. **LLM Provider Abstractions**
|
125
|
+
- Unified interface for multiple providers
|
126
|
+
- Beyond just OpenAI (Anthropic, Cohere, etc.)
|
127
|
+
- Local model support (Ollama, etc.)
|
128
|
+
- Token counting and cost tracking
|
129
|
+
|
130
|
+
### 3. **Advanced Metrics**
|
131
|
+
- F1, BLEU, ROUGE scores
|
132
|
+
- LLM-as-Judge implementations
|
133
|
+
- Composite metric builders
|
134
|
+
- Batch evaluation utilities
|
135
|
+
|
136
|
+
### 4. **Streaming Support**
|
137
|
+
- Token-by-token streaming
|
138
|
+
- Progressive output display
|
139
|
+
- Useful for long generations
|
140
|
+
|
141
|
+
### 5. **Serialization**
|
142
|
+
- Save/load compiled programs
|
143
|
+
- Export optimized parameters
|
144
|
+
- Model versioning support
|
145
|
+
|
146
|
+
### 6. **Settings Management**
|
147
|
+
- Global configuration system
|
148
|
+
- Provider-specific settings
|
149
|
+
- Experiment tracking
|
150
|
+
|
151
|
+
### 7. **Advanced Caching**
|
152
|
+
- Request deduplication
|
153
|
+
- Semantic caching options
|
154
|
+
- Cache invalidation strategies
|
155
|
+
|
156
|
+
### 8. **Parallel/Async Execution**
|
157
|
+
- Batch processing optimizations
|
158
|
+
- Concurrent module execution
|
159
|
+
- Async compilation runs
|
160
|
+
|
161
|
+
### 9. **ColBERTv2 Integration**
|
162
|
+
- Advanced retrieval model
|
163
|
+
- Better than basic vector search
|
164
|
+
- Optimized for retrieval tasks
|
165
|
+
|
166
|
+
### 10. **Logging and Debugging**
|
167
|
+
- Detailed trace visualization
|
168
|
+
- Cost tracking and reporting
|
169
|
+
- Performance profiling
|
170
|
+
|
171
|
+
## Priority Recommendations
|
172
|
+
|
173
|
+
### High Priority (Core Functionality)
|
174
|
+
1. Example/Prediction classes
|
175
|
+
2. Trace collection system
|
176
|
+
3. MIPROv2 optimizer
|
177
|
+
4. ProgramOfThought module
|
178
|
+
5. Compilation infrastructure
|
179
|
+
|
180
|
+
### Medium Priority (Enhanced Capabilities)
|
181
|
+
1. MultiChainComparison
|
182
|
+
2. BestOfN module
|
183
|
+
3. Typed predictors
|
184
|
+
4. Additional optimizers (COPRO, KNNFewShot)
|
185
|
+
5. Data loaders
|
186
|
+
|
187
|
+
### Low Priority (Nice to Have)
|
188
|
+
1. Advanced metrics
|
189
|
+
2. Streaming support
|
190
|
+
3. ColBERTv2 integration
|
191
|
+
4. Ensemble optimizer
|
192
|
+
5. Signature optimizers
|