desiru 0.1.0 → 0.2.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 +4 -4
- data/.claude/settings.local.json +11 -0
- data/.env.example +34 -0
- data/.rubocop.yml +7 -4
- data/.ruby-version +1 -0
- data/CHANGELOG.md +73 -0
- data/CLAUDE.local.md +3 -0
- data/CLAUDE.md +10 -1
- data/Gemfile +21 -2
- data/Gemfile.lock +88 -13
- data/README.md +301 -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-development-swarm.yml +185 -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/core/compiler.rb +231 -0
- data/lib/desiru/core/example.rb +96 -0
- data/lib/desiru/core/prediction.rb +108 -0
- data/lib/desiru/core/trace.rb +330 -0
- data/lib/desiru/core/traceable.rb +61 -0
- data/lib/desiru/core.rb +12 -0
- 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 +67 -9
- data/lib/desiru/modules/best_of_n.rb +306 -0
- 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 +256 -0
- data/lib/desiru/modules/predict.rb +15 -1
- data/lib/desiru/modules/program_of_thought.rb +338 -0
- data/lib/desiru/modules/react.rb +273 -0
- data/lib/desiru/modules/retrieve.rb +4 -2
- data/lib/desiru/optimizers/base.rb +32 -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/optimizers/mipro_v2.rb +889 -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 +33 -8
- data/missing-features-analysis.md +192 -0
- metadata +75 -45
- data/lib/desiru/models/raix_adapter.rb +0 -210
data/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
A Ruby implementation of [DSPy](https://dspy.ai/), the framework for programming—not prompting—language models. Build sophisticated AI systems with modular, composable code instead of brittle prompt strings.
|
|
4
4
|
|
|
5
|
+
Note: This project is in active development. While core functionality is stable, expect continued rapid evolution and new features.
|
|
6
|
+
|
|
7
|
+
|
|
5
8
|
## Overview
|
|
6
9
|
|
|
7
10
|
Desiru brings the power of DSPy to the Ruby ecosystem, enabling developers to:
|
|
@@ -10,7 +13,7 @@ Desiru brings the power of DSPy to the Ruby ecosystem, enabling developers to:
|
|
|
10
13
|
- Build portable AI systems that work across different language models
|
|
11
14
|
- Create maintainable, testable AI applications
|
|
12
15
|
|
|
13
|
-
Desiru
|
|
16
|
+
Desiru provides direct integrations with multiple language model providers including OpenAI, Anthropic, and OpenRouter, with features like streaming, function calling, and prompt caching.
|
|
14
17
|
|
|
15
18
|
## Installation
|
|
16
19
|
|
|
@@ -85,6 +88,12 @@ cot = Desiru::ChainOfThought.new("question -> answer")
|
|
|
85
88
|
# ReAct pattern for tool use
|
|
86
89
|
react = Desiru::ReAct.new("question -> answer", tools: [calculator, search])
|
|
87
90
|
|
|
91
|
+
# Program of Thought - generates and executes code
|
|
92
|
+
pot = Desiru::ProgramOfThought.new("problem -> solution: float")
|
|
93
|
+
|
|
94
|
+
# Best of N - samples multiple outputs and selects the best
|
|
95
|
+
best_of_n = Desiru::BestOfN.new("question -> answer", n_samples: 3, selection_criterion: :consistency)
|
|
96
|
+
|
|
88
97
|
# Compose modules into programs
|
|
89
98
|
class RAGPipeline < Desiru::Program
|
|
90
99
|
def initialize
|
|
@@ -187,6 +196,128 @@ model = Desiru::Models::Ollama.new(
|
|
|
187
196
|
cot = Desiru::ChainOfThought.new("question -> answer", model: model)
|
|
188
197
|
```
|
|
189
198
|
|
|
199
|
+
### Assertions and Validation
|
|
200
|
+
|
|
201
|
+
Desiru provides an assertions system for validating module outputs and enforcing constraints:
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
# Configure assertions
|
|
205
|
+
Desiru::Assertions.configure do |config|
|
|
206
|
+
config.max_assertion_retries = 3 # Retry failed assertions up to 3 times
|
|
207
|
+
config.assertion_retry_delay = 0.5 # Wait 0.5s between retries
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Use assertions in your modules
|
|
211
|
+
class FactChecker < Desiru::Module
|
|
212
|
+
def forward(statement:)
|
|
213
|
+
result = @model.complete(prompt: "Verify: #{statement}")
|
|
214
|
+
confidence = extract_confidence(result)
|
|
215
|
+
|
|
216
|
+
# Hard assertion - will retry if confidence is too low
|
|
217
|
+
Desiru.assert(confidence > 0.8, "Confidence too low: #{confidence}")
|
|
218
|
+
|
|
219
|
+
{ statement: statement, confidence: confidence, verified: true }
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Use suggestions for soft constraints
|
|
224
|
+
class CodeReviewer < Desiru::Module
|
|
225
|
+
def forward(code:)
|
|
226
|
+
review = analyze_code(code)
|
|
227
|
+
|
|
228
|
+
# Soft suggestion - logs warning but continues
|
|
229
|
+
Desiru.suggest(review[:test_coverage] > 0.7, "Test coverage below 70%")
|
|
230
|
+
Desiru.suggest(review[:complexity] < 10, "Code complexity too high")
|
|
231
|
+
|
|
232
|
+
review
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Key features:
|
|
238
|
+
- **Assertions** (`Desiru.assert`) - Enforce hard constraints with automatic retries
|
|
239
|
+
- **Suggestions** (`Desiru.suggest`) - Log warnings for soft constraints
|
|
240
|
+
- **Configurable retries** - Control retry behavior for failed assertions
|
|
241
|
+
- **Module integration** - Assertions are fully integrated with the module retry system
|
|
242
|
+
|
|
243
|
+
See `examples/assertions_example.rb` for more detailed examples.
|
|
244
|
+
|
|
245
|
+
### REST API with Grape
|
|
246
|
+
|
|
247
|
+
Desiru provides Grape integration for building REST APIs:
|
|
248
|
+
|
|
249
|
+
```ruby
|
|
250
|
+
require 'desiru/api'
|
|
251
|
+
|
|
252
|
+
# Create API with your modules
|
|
253
|
+
api = Desiru::API::GrapeIntegration.new
|
|
254
|
+
api.register_module('/qa', qa_module, description: 'Question answering')
|
|
255
|
+
api.register_module('/summarize', summarizer, description: 'Text summarization')
|
|
256
|
+
|
|
257
|
+
# Mount as Rack app
|
|
258
|
+
run api.to_rack_app
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Features:
|
|
262
|
+
- **Automatic endpoint generation** from Desiru signatures
|
|
263
|
+
- **Parameter validation** based on signature types
|
|
264
|
+
- **CORS support** built-in
|
|
265
|
+
- **Async support** (when enabled in modules)
|
|
266
|
+
- **Streaming endpoints** for real-time responses
|
|
267
|
+
|
|
268
|
+
Example endpoints:
|
|
269
|
+
```bash
|
|
270
|
+
# Synchronous request
|
|
271
|
+
curl -X POST http://localhost:9292/api/v1/qa \
|
|
272
|
+
-H "Content-Type: application/json" \
|
|
273
|
+
-d '{"question": "What is Ruby?"}'
|
|
274
|
+
|
|
275
|
+
# Async request
|
|
276
|
+
curl -X POST http://localhost:9292/api/v1/summarize \
|
|
277
|
+
-H "Content-Type: application/json" \
|
|
278
|
+
-d '{"text": "Long text...", "max_words": 100, "async": true}'
|
|
279
|
+
|
|
280
|
+
# Check job status
|
|
281
|
+
curl http://localhost:9292/api/v1/jobs/JOB_ID
|
|
282
|
+
|
|
283
|
+
# Check API health
|
|
284
|
+
curl http://localhost:9292/api/v1/health
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
See `examples/rest_api.rb` and `examples/rest_api_advanced.rb` for complete examples.
|
|
288
|
+
|
|
289
|
+
### REST API with Sinatra
|
|
290
|
+
|
|
291
|
+
Desiru also supports Sinatra for lightweight REST APIs:
|
|
292
|
+
|
|
293
|
+
```ruby
|
|
294
|
+
require 'desiru/api'
|
|
295
|
+
|
|
296
|
+
# Create API with Sinatra (lightweight alternative to Grape)
|
|
297
|
+
api = Desiru::API.sinatra do
|
|
298
|
+
register_module '/qa', qa_module, description: 'Question answering'
|
|
299
|
+
register_module '/summarize', summarizer, description: 'Text summarization'
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Or explicitly specify the framework
|
|
303
|
+
api = Desiru::API.create(framework: :sinatra) do
|
|
304
|
+
register_module '/process', processor
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Mount as Rack app
|
|
308
|
+
run api.to_rack_app
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Features:
|
|
312
|
+
- **Lightweight** - Minimal dependencies with Sinatra
|
|
313
|
+
- **Same interface** as Grape integration
|
|
314
|
+
- **Full compatibility** with all Desiru module features
|
|
315
|
+
- **CORS support** built-in
|
|
316
|
+
- **Async support** for background processing
|
|
317
|
+
- **Streaming endpoints** for real-time responses
|
|
318
|
+
|
|
319
|
+
See `examples/sinatra_api.rb` for a complete example.
|
|
320
|
+
|
|
190
321
|
### Background Processing
|
|
191
322
|
|
|
192
323
|
Desiru includes built-in support for asynchronous processing using Sidekiq:
|
|
@@ -201,8 +332,10 @@ end
|
|
|
201
332
|
module = Desiru::Predict.new("question -> answer")
|
|
202
333
|
result = module.call_async(question: "What is 2+2?")
|
|
203
334
|
|
|
204
|
-
# Check status
|
|
335
|
+
# Check status and progress
|
|
205
336
|
result.ready? # => false (still processing)
|
|
337
|
+
result.status # => "running", "completed", "failed", etc.
|
|
338
|
+
result.progress # => 0-100 (percentage complete)
|
|
206
339
|
result.success? # => true/false (when ready)
|
|
207
340
|
|
|
208
341
|
# Wait for result
|
|
@@ -267,6 +400,172 @@ This approach makes Desiru particularly well-suited for:
|
|
|
267
400
|
- Systems requiring job persistence and reliability
|
|
268
401
|
- Deployments that need to scale horizontally
|
|
269
402
|
|
|
403
|
+
### Database Persistence with Sequel
|
|
404
|
+
|
|
405
|
+
Desiru includes a comprehensive persistence layer using Sequel for tracking:
|
|
406
|
+
- Module execution history and performance metrics
|
|
407
|
+
- API request/response data for analytics
|
|
408
|
+
- Training examples and optimization results
|
|
409
|
+
- Model performance over time
|
|
410
|
+
|
|
411
|
+
```ruby
|
|
412
|
+
# Configure persistence
|
|
413
|
+
require 'desiru/persistence'
|
|
414
|
+
|
|
415
|
+
Desiru::Persistence.database_url = 'postgres://localhost/desiru'
|
|
416
|
+
Desiru::Persistence.connect!
|
|
417
|
+
Desiru::Persistence.migrate!
|
|
418
|
+
|
|
419
|
+
# Track module executions
|
|
420
|
+
execution = Desiru::Persistence[:module_executions].create_for_module(
|
|
421
|
+
'TextSummarizer',
|
|
422
|
+
{ text: 'Long article...' }
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
# Complete with results
|
|
426
|
+
Desiru::Persistence[:module_executions].complete(
|
|
427
|
+
execution.id,
|
|
428
|
+
{ summary: 'Short summary' },
|
|
429
|
+
{ model: 'gpt-3.5-turbo', tokens: 150 }
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
# Query performance metrics
|
|
433
|
+
repo = Desiru::Persistence[:module_executions]
|
|
434
|
+
puts "Success rate: #{repo.success_rate('TextSummarizer')}%"
|
|
435
|
+
puts "Average duration: #{repo.average_duration('TextSummarizer')}s"
|
|
436
|
+
|
|
437
|
+
# Store training examples
|
|
438
|
+
examples = [
|
|
439
|
+
{ inputs: { text: 'Example 1' }, outputs: { summary: 'Summary 1' } },
|
|
440
|
+
{ inputs: { text: 'Example 2' }, outputs: { summary: 'Summary 2' } }
|
|
441
|
+
]
|
|
442
|
+
|
|
443
|
+
Desiru::Persistence[:training_examples].bulk_create('TextSummarizer', examples)
|
|
444
|
+
|
|
445
|
+
# Export for training
|
|
446
|
+
data = Desiru::Persistence[:training_examples].export_for_training(
|
|
447
|
+
'TextSummarizer',
|
|
448
|
+
format: :dspy
|
|
449
|
+
)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### API Request Tracking
|
|
453
|
+
|
|
454
|
+
Automatically track all API requests with the persistence middleware:
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
# Add persistence to your API
|
|
458
|
+
api = Desiru::API.create do
|
|
459
|
+
register_module '/summarize', summarizer
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Enable automatic request tracking
|
|
463
|
+
app = api.with_persistence(enabled: true)
|
|
464
|
+
|
|
465
|
+
# Query API metrics
|
|
466
|
+
requests = Desiru::Persistence[:api_requests]
|
|
467
|
+
puts "Requests per minute: #{requests.requests_per_minute}"
|
|
468
|
+
puts "Average response time: #{requests.average_response_time}s"
|
|
469
|
+
puts "Top endpoints: #{requests.top_paths(5)}"
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Features:
|
|
473
|
+
- **Automatic tracking** of all API requests and module executions
|
|
474
|
+
- **Performance analytics** including success rates and response times
|
|
475
|
+
- **Training data management** with dataset splitting and export
|
|
476
|
+
- **Optimization tracking** to measure improvements over time
|
|
477
|
+
- **Multiple database support** via Sequel (PostgreSQL, MySQL, SQLite)
|
|
478
|
+
|
|
479
|
+
### ReAct Module (Tool-Using Agents)
|
|
480
|
+
|
|
481
|
+
The ReAct module enables building AI agents that can reason about tasks and use tools to gather information:
|
|
482
|
+
|
|
483
|
+
```ruby
|
|
484
|
+
# Define tools for your agent
|
|
485
|
+
class WeatherTool
|
|
486
|
+
def self.name
|
|
487
|
+
"get_weather"
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
def self.description
|
|
491
|
+
"Get current weather for a city. Args: city (string)"
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
def self.call(city:)
|
|
495
|
+
# Your weather API integration
|
|
496
|
+
"Current weather in #{city}: sunny, 72°F"
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
# Create a ReAct agent with tools
|
|
501
|
+
tools = [WeatherTool, CalculatorTool]
|
|
502
|
+
agent = Desiru::Modules::ReAct.new(
|
|
503
|
+
'question: string -> answer: string',
|
|
504
|
+
tools: tools,
|
|
505
|
+
max_iterations: 5
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
# The agent will reason and use tools to answer
|
|
509
|
+
result = agent.call(
|
|
510
|
+
question: "What's the weather in Tokyo and is 72°F warm in Celsius?"
|
|
511
|
+
)
|
|
512
|
+
# The agent will:
|
|
513
|
+
# 1. Call get_weather tool for Tokyo
|
|
514
|
+
# 2. Use calculator to convert 72°F to Celsius
|
|
515
|
+
# 3. Synthesize the final answer
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
Key features:
|
|
519
|
+
- **Flexible tool format**: Pass tools as classes, hashes, or callables
|
|
520
|
+
- **Automatic reasoning**: The agent decides which tools to use and when
|
|
521
|
+
- **Trajectory management**: Automatically handles long conversations
|
|
522
|
+
- **Error handling**: Gracefully handles tool execution failures
|
|
523
|
+
- **Iteration limits**: Prevents infinite loops
|
|
524
|
+
|
|
525
|
+
### GraphQL Integration
|
|
526
|
+
|
|
527
|
+
Desiru provides GraphQL integration with automatic schema generation and efficient batch loading:
|
|
528
|
+
|
|
529
|
+
```ruby
|
|
530
|
+
require 'desiru/graphql'
|
|
531
|
+
|
|
532
|
+
# Register your Desiru modules
|
|
533
|
+
generator = Desiru::GraphQL::SchemaGenerator.new
|
|
534
|
+
generator.register_signature('questionAnswer', qa_module)
|
|
535
|
+
generator.register_signature('summarize', summarizer_module)
|
|
536
|
+
|
|
537
|
+
# Generate GraphQL schema
|
|
538
|
+
schema = generator.generate_schema
|
|
539
|
+
|
|
540
|
+
# Use with your GraphQL server
|
|
541
|
+
result = schema.execute(
|
|
542
|
+
query,
|
|
543
|
+
context: { current_user: user },
|
|
544
|
+
variables: variables
|
|
545
|
+
)
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
Features include:
|
|
549
|
+
- **Automatic schema generation** from Desiru signatures
|
|
550
|
+
- **DataLoader pattern** for N+1 query prevention
|
|
551
|
+
- **Batch execution** for multiple queries
|
|
552
|
+
- **Type mapping** including support for Literal types as GraphQL enums
|
|
553
|
+
- **Thread-safe** promise-based lazy loading
|
|
554
|
+
|
|
555
|
+
#### GraphQL Batch Loading Example
|
|
556
|
+
|
|
557
|
+
```ruby
|
|
558
|
+
# The executor automatically batches multiple field requests
|
|
559
|
+
executor = Desiru::GraphQL::Executor.new(schema)
|
|
560
|
+
|
|
561
|
+
# Execute multiple queries efficiently in a single batch
|
|
562
|
+
results = executor.execute_batch([
|
|
563
|
+
{ query: query1, variables: vars1 },
|
|
564
|
+
{ query: query2, variables: vars2 }
|
|
565
|
+
])
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
|
|
270
569
|
## Examples
|
|
271
570
|
|
|
272
571
|
### Retrieval-Augmented Generation (RAG)
|
data/Rakefile
CHANGED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
up do
|
|
5
|
+
# API Requests table
|
|
6
|
+
create_table(:api_requests) do
|
|
7
|
+
primary_key :id
|
|
8
|
+
String :method, null: false
|
|
9
|
+
String :path, null: false
|
|
10
|
+
String :remote_ip
|
|
11
|
+
Integer :status_code, null: false
|
|
12
|
+
Float :response_time
|
|
13
|
+
String :headers, text: true # JSON
|
|
14
|
+
String :params, text: true # JSON
|
|
15
|
+
String :response_body, text: true # JSON
|
|
16
|
+
String :error_message
|
|
17
|
+
DateTime :created_at, null: false
|
|
18
|
+
DateTime :updated_at, null: false
|
|
19
|
+
|
|
20
|
+
index :path
|
|
21
|
+
index :status_code
|
|
22
|
+
index :created_at
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Module Executions table
|
|
26
|
+
create_table(:module_executions) do
|
|
27
|
+
primary_key :id
|
|
28
|
+
foreign_key :api_request_id, :api_requests, on_delete: :cascade
|
|
29
|
+
String :module_name, null: false
|
|
30
|
+
String :module_type
|
|
31
|
+
String :status, null: false, default: 'pending'
|
|
32
|
+
String :inputs, text: true # JSON
|
|
33
|
+
String :outputs, text: true # JSON
|
|
34
|
+
String :metadata, text: true # JSON
|
|
35
|
+
String :error_message
|
|
36
|
+
String :error_backtrace, text: true
|
|
37
|
+
DateTime :started_at, null: false
|
|
38
|
+
DateTime :finished_at
|
|
39
|
+
DateTime :created_at, null: false
|
|
40
|
+
DateTime :updated_at, null: false
|
|
41
|
+
|
|
42
|
+
index :module_name
|
|
43
|
+
index :status
|
|
44
|
+
index :started_at
|
|
45
|
+
index %i[module_name status]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Optimization Results table
|
|
49
|
+
create_table(:optimization_results) do
|
|
50
|
+
primary_key :id
|
|
51
|
+
String :module_name, null: false
|
|
52
|
+
String :optimizer_type, null: false
|
|
53
|
+
Float :score, null: false
|
|
54
|
+
Float :baseline_score
|
|
55
|
+
Integer :training_size
|
|
56
|
+
Integer :validation_size
|
|
57
|
+
String :parameters, text: true # JSON
|
|
58
|
+
String :metrics, text: true # JSON
|
|
59
|
+
String :best_prompts, text: true # JSON
|
|
60
|
+
DateTime :started_at
|
|
61
|
+
DateTime :finished_at
|
|
62
|
+
DateTime :created_at, null: false
|
|
63
|
+
DateTime :updated_at, null: false
|
|
64
|
+
|
|
65
|
+
index :module_name
|
|
66
|
+
index :optimizer_type
|
|
67
|
+
index :score
|
|
68
|
+
index %i[module_name optimizer_type]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Training Examples table
|
|
72
|
+
create_table(:training_examples) do
|
|
73
|
+
primary_key :id
|
|
74
|
+
String :module_name, null: false
|
|
75
|
+
String :dataset_type, default: 'training'
|
|
76
|
+
String :inputs, text: true, null: false # JSON
|
|
77
|
+
String :expected_outputs, text: true # JSON
|
|
78
|
+
String :metadata, text: true # JSON
|
|
79
|
+
Integer :used_count, default: 0
|
|
80
|
+
DateTime :last_used_at
|
|
81
|
+
DateTime :created_at, null: false
|
|
82
|
+
DateTime :updated_at, null: false
|
|
83
|
+
|
|
84
|
+
index :module_name
|
|
85
|
+
index :dataset_type
|
|
86
|
+
index %i[module_name dataset_type]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
down do
|
|
91
|
+
drop_table(:training_examples)
|
|
92
|
+
drop_table(:optimization_results)
|
|
93
|
+
drop_table(:module_executions)
|
|
94
|
+
drop_table(:api_requests)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
up do
|
|
5
|
+
# Job Results table for persisting background job results
|
|
6
|
+
create_table(:job_results) do
|
|
7
|
+
primary_key :id
|
|
8
|
+
String :job_id, null: false, unique: true
|
|
9
|
+
String :job_class, null: false
|
|
10
|
+
String :queue, null: false
|
|
11
|
+
String :status, null: false, default: 'pending' # pending, processing, completed, failed
|
|
12
|
+
Integer :progress, default: 0
|
|
13
|
+
String :message
|
|
14
|
+
String :inputs, text: true # JSON
|
|
15
|
+
String :result, text: true # JSON
|
|
16
|
+
String :error_message
|
|
17
|
+
String :error_backtrace, text: true
|
|
18
|
+
Integer :retry_count, default: 0
|
|
19
|
+
DateTime :enqueued_at, null: false
|
|
20
|
+
DateTime :started_at
|
|
21
|
+
DateTime :finished_at
|
|
22
|
+
DateTime :expires_at
|
|
23
|
+
DateTime :created_at, null: false
|
|
24
|
+
DateTime :updated_at, null: false
|
|
25
|
+
|
|
26
|
+
index :job_id
|
|
27
|
+
index :job_class
|
|
28
|
+
index :status
|
|
29
|
+
index :queue
|
|
30
|
+
index :created_at
|
|
31
|
+
index :expires_at
|
|
32
|
+
index %i[job_class status]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
down do
|
|
37
|
+
drop_table(:job_results)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
swarm:
|
|
3
|
+
name: "Desiru Development Team"
|
|
4
|
+
main: project_lead
|
|
5
|
+
before:
|
|
6
|
+
- "echo '🚀 Starting Desiru development session...'"
|
|
7
|
+
- "shadowenv exec -- bundle install"
|
|
8
|
+
- "shadowenv exec -- bundle exec rspec --help > /dev/null || echo 'RSpec ready'"
|
|
9
|
+
instances:
|
|
10
|
+
project_lead:
|
|
11
|
+
description: "Project lead coordinating Desiru development, managing releases, and ensuring code quality"
|
|
12
|
+
directory: .
|
|
13
|
+
model: opus
|
|
14
|
+
connections: [core_architect, feature_implementer, test_specialist, release_manager]
|
|
15
|
+
prompt: |
|
|
16
|
+
You are the project lead for Desiru, a Ruby implementation of DSPy. Your responsibilities include:
|
|
17
|
+
|
|
18
|
+
- Coordinating development work across the team
|
|
19
|
+
- Making architectural decisions and ensuring code quality
|
|
20
|
+
- Prioritizing GitHub issues based on the roadmap
|
|
21
|
+
- Reviewing code changes before they're committed
|
|
22
|
+
- Managing the overall development process
|
|
23
|
+
|
|
24
|
+
Key project context:
|
|
25
|
+
- This is a Ruby gem implementing DSPy (Declarative Self-Improving) for programming language models
|
|
26
|
+
- Current version: 0.1.1 (check lib/desiru/version.rb)
|
|
27
|
+
- Uses RSpec for testing (NEVER use Minitest)
|
|
28
|
+
- Follows Ruby community conventions
|
|
29
|
+
- Has a comprehensive roadmap in issue #22
|
|
30
|
+
|
|
31
|
+
Always use 'shadowenv exec --' prefix for Ruby/bundler commands. Use 'be' alias for bundle exec.
|
|
32
|
+
|
|
33
|
+
For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
34
|
+
allowed_tools:
|
|
35
|
+
- Read
|
|
36
|
+
- Edit
|
|
37
|
+
- Bash
|
|
38
|
+
- WebSearch
|
|
39
|
+
- WebFetch
|
|
40
|
+
|
|
41
|
+
core_architect:
|
|
42
|
+
description: "Senior architect implementing core DSPy infrastructure, modules, and optimizers"
|
|
43
|
+
directory: ./lib/desiru
|
|
44
|
+
model: opus
|
|
45
|
+
connections: [feature_implementer, test_specialist]
|
|
46
|
+
prompt: |
|
|
47
|
+
You are the core architect for Desiru's DSPy implementation. Your expertise includes:
|
|
48
|
+
|
|
49
|
+
- Implementing core DSPy modules (ProgramOfThought, MultiChainComparison, BestOfN)
|
|
50
|
+
- Building optimizers (MIPROv2, COPRO, BootstrapFewShotWithRandomSearch)
|
|
51
|
+
- Designing the compilation infrastructure and trace collection system
|
|
52
|
+
- Creating typed predictors and example/prediction classes
|
|
53
|
+
|
|
54
|
+
Focus on high-priority features from the roadmap (issue #22):
|
|
55
|
+
- Phase 1: Core Functionality (Example/Prediction classes, ProgramOfThought, MIPROv2, Trace collection)
|
|
56
|
+
- Phase 2: Enhanced Optimization (MultiChainComparison, BestOfN, COPRO)
|
|
57
|
+
|
|
58
|
+
Always follow Ruby conventions and ensure code is clean, well-documented, and tested.
|
|
59
|
+
Use 'shadowenv exec --' for Ruby commands and 'be' for bundle exec.
|
|
60
|
+
|
|
61
|
+
For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
62
|
+
allowed_tools:
|
|
63
|
+
- Read
|
|
64
|
+
- Edit
|
|
65
|
+
- Write
|
|
66
|
+
- Bash
|
|
67
|
+
|
|
68
|
+
feature_implementer:
|
|
69
|
+
description: "Feature developer implementing specific DSPy components, utilities, and integrations"
|
|
70
|
+
directory: ./lib/desiru
|
|
71
|
+
model: opus
|
|
72
|
+
connections: [test_specialist]
|
|
73
|
+
prompt: |
|
|
74
|
+
You are a feature developer specializing in implementing specific DSPy components. Your focus areas:
|
|
75
|
+
|
|
76
|
+
- Implementing modules: Refine, ChainOfThoughtWithHint, streaming support
|
|
77
|
+
- Building utilities: data loaders, metrics system, serialization
|
|
78
|
+
- Creating multi-provider LLM abstractions
|
|
79
|
+
- Adding advanced features like suggestions system
|
|
80
|
+
|
|
81
|
+
Current priority features (from roadmap issue #22):
|
|
82
|
+
- Medium priority: Refine module, ChainOfThoughtWithHint, advanced metrics
|
|
83
|
+
- Utilities: Data loaders (CSV, JSON), streaming support, serialization
|
|
84
|
+
|
|
85
|
+
Ensure all implementations follow existing patterns and are thoroughly tested.
|
|
86
|
+
Use 'shadowenv exec --' for Ruby commands and 'be' for bundle exec.
|
|
87
|
+
|
|
88
|
+
For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
89
|
+
allowed_tools:
|
|
90
|
+
- Read
|
|
91
|
+
- Edit
|
|
92
|
+
- Write
|
|
93
|
+
- Bash
|
|
94
|
+
|
|
95
|
+
test_specialist:
|
|
96
|
+
description: "Testing expert ensuring comprehensive test coverage and quality assurance"
|
|
97
|
+
directory: ./spec
|
|
98
|
+
model: sonnet
|
|
99
|
+
prompt: |
|
|
100
|
+
You are the testing specialist for Desiru. Your responsibilities include:
|
|
101
|
+
|
|
102
|
+
- Writing comprehensive RSpec tests for all new features
|
|
103
|
+
- Ensuring test coverage for core functionality
|
|
104
|
+
- Creating integration tests for DSPy workflows
|
|
105
|
+
- Maintaining test quality and performance
|
|
106
|
+
- Running test suites and fixing test failures
|
|
107
|
+
|
|
108
|
+
CRITICAL: This project uses RSpec exclusively. NEVER use Minitest or create test/ directories.
|
|
109
|
+
All tests must be in spec/ directory using RSpec format.
|
|
110
|
+
|
|
111
|
+
Key testing priorities:
|
|
112
|
+
- Round-trip serialization tests
|
|
113
|
+
- Integration tests for modules and optimizers
|
|
114
|
+
- Performance benchmarks
|
|
115
|
+
- Cross-version compatibility tests
|
|
116
|
+
|
|
117
|
+
Use 'shadowenv exec --' for Ruby commands and 'be rspec' for running tests.
|
|
118
|
+
|
|
119
|
+
For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
120
|
+
allowed_tools:
|
|
121
|
+
- Read
|
|
122
|
+
- Edit
|
|
123
|
+
- Write
|
|
124
|
+
- Bash
|
|
125
|
+
|
|
126
|
+
release_manager:
|
|
127
|
+
description: "Release engineering specialist handling versioning, changelogs, and gem publishing"
|
|
128
|
+
directory: .
|
|
129
|
+
model: sonnet
|
|
130
|
+
prompt: |
|
|
131
|
+
You are the release manager for Desiru. Your responsibilities include:
|
|
132
|
+
|
|
133
|
+
- Managing semantic versioning in lib/desiru/version.rb
|
|
134
|
+
- Updating CHANGELOG.md with new features and fixes
|
|
135
|
+
- Preparing release documentation
|
|
136
|
+
- Coordinating gem publishing to RubyGems
|
|
137
|
+
- Ensuring release readiness (tests pass, docs updated)
|
|
138
|
+
|
|
139
|
+
Current version: 0.1.1 (check lib/desiru/version.rb)
|
|
140
|
+
|
|
141
|
+
Release process:
|
|
142
|
+
1. Update version number in lib/desiru/version.rb
|
|
143
|
+
2. Update CHANGELOG.md with version changes
|
|
144
|
+
3. Commit changes: git commit -am "Bump version to x.y.z"
|
|
145
|
+
4. Create version tag: git tag -a vx.y.z -m "Release version x.y.z"
|
|
146
|
+
5. Push changes and tag: git push && git push --tags
|
|
147
|
+
|
|
148
|
+
Use 'shadowenv exec --' for Ruby commands and follow semantic versioning.
|
|
149
|
+
Coordinate with project_lead before any releases.
|
|
150
|
+
|
|
151
|
+
For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
152
|
+
allowed_tools:
|
|
153
|
+
- Read
|
|
154
|
+
- Edit
|
|
155
|
+
- Bash
|
|
156
|
+
- WebSearch
|
|
157
|
+
|
|
158
|
+
documentation_writer:
|
|
159
|
+
description: "Documentation specialist maintaining comprehensive docs and examples"
|
|
160
|
+
directory: ./docs
|
|
161
|
+
model: sonnet
|
|
162
|
+
connections: [project_lead]
|
|
163
|
+
prompt: |
|
|
164
|
+
You are the documentation specialist for Desiru. Your focus areas:
|
|
165
|
+
|
|
166
|
+
- Maintaining comprehensive API documentation
|
|
167
|
+
- Creating usage examples and tutorials
|
|
168
|
+
- Updating feature documentation as new capabilities are added
|
|
169
|
+
- Ensuring documentation accuracy and clarity
|
|
170
|
+
- Writing integration guides and best practices
|
|
171
|
+
|
|
172
|
+
Key documentation areas:
|
|
173
|
+
- Feature gap analysis updates
|
|
174
|
+
- Integration test strategy documentation
|
|
175
|
+
- API documentation for new modules and optimizers
|
|
176
|
+
- Usage examples for new features
|
|
177
|
+
|
|
178
|
+
Keep documentation current with development progress and ensure examples work.
|
|
179
|
+
|
|
180
|
+
For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
181
|
+
allowed_tools:
|
|
182
|
+
- Read
|
|
183
|
+
- Edit
|
|
184
|
+
- Write
|
|
185
|
+
- WebSearch
|
data/desiru.db
ADDED
|
Binary file
|
data/desiru.gemspec
CHANGED
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
'enabling reliable, maintainable, and portable AI programming.'
|
|
14
14
|
spec.homepage = 'https://github.com/obie/desiru'
|
|
15
15
|
spec.license = 'MIT'
|
|
16
|
-
spec.required_ruby_version = '>= 3.
|
|
16
|
+
spec.required_ruby_version = '>= 3.3.0'
|
|
17
17
|
|
|
18
18
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
19
19
|
spec.metadata['source_code_uri'] = 'https://github.com/obie/desiru'
|
|
@@ -36,9 +36,6 @@ Gem::Specification.new do |spec|
|
|
|
36
36
|
spec.add_dependency 'sidekiq', '~> 7.2'
|
|
37
37
|
spec.add_dependency 'singleton', '~> 0.1'
|
|
38
38
|
|
|
39
|
-
# Development dependencies
|
|
40
|
-
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
41
|
-
spec.add_development_dependency 'rake', '~> 13.0'
|
|
42
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
39
|
+
# Development dependencies moved to Gemfile
|
|
43
40
|
spec.metadata['rubygems_mfa_required'] = 'false'
|
|
44
41
|
end
|