sorbet-baml 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.md +94 -0
- data/README.md +197 -125
- data/examples/description_parameters.rb +49 -0
- data/lib/sorbet_baml/comment_extractor.rb +23 -18
- data/lib/sorbet_baml/converter.rb +3 -3
- data/lib/sorbet_baml/description_extension.rb +34 -0
- data/lib/sorbet_baml/description_extractor.rb +36 -0
- data/lib/sorbet_baml/version.rb +1 -1
- data/lib/sorbet_baml.rb +3 -0
- metadata +5 -6
- data/docs/README.md +0 -117
- data/docs/advanced-usage.md +0 -427
- data/docs/getting-started.md +0 -91
- data/docs/troubleshooting.md +0 -291
- data/docs/type-mapping.md +0 -192
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6ebc9d978b525e29a1a19ef184f073393d6a588e54d84dc2b9fd7034d1fa40c
|
|
4
|
+
data.tar.gz: f7d5e028fe65a4a4cc9b19c60dc17dd65fd13353634e55201db5189bb457447a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40b4736cc561b5135ee32e08543148c018ea9963e016c6cbb66697cd346ff7cf30f7438d370853c045b40d062a47f38d7aaa1a9c6c8e92f8e7f6721b495966e0
|
|
7
|
+
data.tar.gz: 0caf0a19906655bbfae88723bbe5b38301601c1523c3cc3b8dc31a15bf6bdd02ceacb790cf0d4bddf718c1162ba51d7b0fcd08110578616cd7c7ac27272bcd42
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Development Commands
|
|
6
|
+
|
|
7
|
+
**Running Tests:**
|
|
8
|
+
```bash
|
|
9
|
+
bundle exec rspec # Run all tests
|
|
10
|
+
bundle exec rspec spec/path_spec.rb # Run specific test file
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Type Checking:**
|
|
14
|
+
```bash
|
|
15
|
+
bundle exec srb tc # Run Sorbet type checker
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Development Setup:**
|
|
19
|
+
```bash
|
|
20
|
+
bundle install # Install dependencies
|
|
21
|
+
bundle exec tapioca dsl # Generate RBI files for gems
|
|
22
|
+
bundle exec tapioca gem # Generate RBI files for dependencies
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Linting:**
|
|
26
|
+
```bash
|
|
27
|
+
bundle exec rubocop # Run RuboCop linter
|
|
28
|
+
bundle exec rubocop -a # Auto-fix violations where possible
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Gem Tasks:**
|
|
32
|
+
```bash
|
|
33
|
+
bundle exec rake build # Build the gem
|
|
34
|
+
bundle exec rake install # Install locally
|
|
35
|
+
bundle exec rake release # Release to RubyGems (maintainers only)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Code Architecture
|
|
39
|
+
|
|
40
|
+
### Core Components
|
|
41
|
+
|
|
42
|
+
**Main Library Entry Point:**
|
|
43
|
+
- `lib/sorbet_baml.rb` - Main module with public API methods and extension loading
|
|
44
|
+
|
|
45
|
+
**Core Conversion System:**
|
|
46
|
+
- `lib/sorbet_baml/converter.rb` - Main converter orchestrating BAML generation
|
|
47
|
+
- `lib/sorbet_baml/type_mapper.rb` - Maps Sorbet type objects to BAML type strings
|
|
48
|
+
- `lib/sorbet_baml/dependency_resolver.rb` - Handles topological sorting of dependencies
|
|
49
|
+
|
|
50
|
+
**Ruby-Idiomatic API Extensions:**
|
|
51
|
+
- `lib/sorbet_baml/struct_extensions.rb` - Adds `.to_baml` method to T::Struct
|
|
52
|
+
- `lib/sorbet_baml/enum_extensions.rb` - Adds `.to_baml` method to T::Enum
|
|
53
|
+
|
|
54
|
+
**Field Documentation:**
|
|
55
|
+
- `lib/sorbet_baml/comment_extractor.rb` - Extracts comments from source for field descriptions
|
|
56
|
+
|
|
57
|
+
### Key Design Patterns
|
|
58
|
+
|
|
59
|
+
**Extension Pattern:** The gem extends T::Struct and T::Enum classes with `.to_baml` methods for a Ruby-idiomatic API.
|
|
60
|
+
|
|
61
|
+
**Dependency Resolution:** Uses topological sorting to ensure dependencies are output before types that reference them, preventing forward reference issues.
|
|
62
|
+
|
|
63
|
+
**Type Mapping:** Comprehensive mapping from Sorbet type system to BAML types:
|
|
64
|
+
- `T::Struct` → BAML classes
|
|
65
|
+
- `T::Enum` → BAML enums
|
|
66
|
+
- `T.nilable(T)` → optional types (`T?`)
|
|
67
|
+
- `T::Array[T]` → array types (`T[]`)
|
|
68
|
+
- `T::Hash[K,V]` → map types (`map<K,V>`)
|
|
69
|
+
- `T.any(T1, T2)` → union types (`T1 | T2`)
|
|
70
|
+
|
|
71
|
+
**Smart Defaults:** The API includes dependencies and field descriptions by default.
|
|
72
|
+
|
|
73
|
+
### Type System Support
|
|
74
|
+
|
|
75
|
+
The gem provides complete coverage of Sorbet's type system:
|
|
76
|
+
- Basic types (String, Integer, Float, Boolean, Symbol, Date/Time)
|
|
77
|
+
- Complex types (Arrays, Hashes, Unions, Nilable)
|
|
78
|
+
- Structured types (T::Struct, T::Enum with full nesting support)
|
|
79
|
+
- Circular reference handling to prevent infinite loops
|
|
80
|
+
|
|
81
|
+
### Testing Structure
|
|
82
|
+
|
|
83
|
+
- `spec/fixtures/` - Test data including complex type examples
|
|
84
|
+
- `spec/integration/` - End-to-end feature tests
|
|
85
|
+
- `spec/sorbet_baml/` - Unit tests for each component
|
|
86
|
+
- Comprehensive test coverage includes edge cases, circular references, and complex type combinations
|
|
87
|
+
|
|
88
|
+
## Development Guidelines
|
|
89
|
+
|
|
90
|
+
**Type Safety:** All code uses `# typed: strict` and maintains full Sorbet compliance.
|
|
91
|
+
|
|
92
|
+
**Ruby Idioms:** The public API follows Ruby conventions with `.to_baml` instance methods rather than static factory methods.
|
|
93
|
+
|
|
94
|
+
**Field Descriptions:** Comments above field definitions are automatically extracted and included as BAML `@description` annotations for LLM context.
|
data/README.md
CHANGED
|
@@ -15,25 +15,43 @@ When working with LLMs, token efficiency directly impacts:
|
|
|
15
15
|
|
|
16
16
|
BAML provides the perfect balance: concise, readable, and LLM-friendly.
|
|
17
17
|
|
|
18
|
-
### Example
|
|
18
|
+
### Example: Autonomous Research Workflow
|
|
19
19
|
|
|
20
20
|
```ruby
|
|
21
|
-
#
|
|
22
|
-
class
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
# Complex LLM workflow types for autonomous research
|
|
22
|
+
class ComplexityLevel < T::Enum
|
|
23
|
+
enums do
|
|
24
|
+
# Basic analysis requiring straightforward research
|
|
25
|
+
Basic = new('basic')
|
|
26
|
+
# Advanced analysis requiring deep domain expertise
|
|
27
|
+
Advanced = new('advanced')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class TaskDecomposition < T::Struct
|
|
32
|
+
# The main research topic being investigated
|
|
33
|
+
const :research_topic, String
|
|
34
|
+
# Target complexity level for the decomposition
|
|
35
|
+
const :complexity_level, ComplexityLevel
|
|
36
|
+
# Autonomously generated list of research subtasks
|
|
37
|
+
const :subtasks, T::Array[String]
|
|
38
|
+
# Strategic priority rankings for each subtask
|
|
39
|
+
const :priority_order, T::Array[Integer]
|
|
27
40
|
end
|
|
28
41
|
|
|
29
|
-
# Ruby-idiomatic conversion
|
|
30
|
-
|
|
42
|
+
# Ruby-idiomatic conversion with dependencies
|
|
43
|
+
TaskDecomposition.to_baml
|
|
31
44
|
# =>
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
45
|
+
# enum ComplexityLevel {
|
|
46
|
+
# "basic" @description("Basic analysis requiring straightforward research")
|
|
47
|
+
# "advanced" @description("Advanced analysis requiring deep domain expertise")
|
|
48
|
+
# }
|
|
49
|
+
#
|
|
50
|
+
# class TaskDecomposition {
|
|
51
|
+
# research_topic string @description("The main research topic being investigated")
|
|
52
|
+
# complexity_level ComplexityLevel @description("Target complexity level for the decomposition")
|
|
53
|
+
# subtasks string[] @description("Autonomously generated list of research subtasks")
|
|
54
|
+
# priority_order int[] @description("Strategic priority rankings for each subtask")
|
|
37
55
|
# }
|
|
38
56
|
```
|
|
39
57
|
|
|
@@ -56,107 +74,120 @@ gem install sorbet-baml
|
|
|
56
74
|
```ruby
|
|
57
75
|
require 'sorbet-baml'
|
|
58
76
|
|
|
59
|
-
# 🎯 Ruby-idiomatic API
|
|
77
|
+
# 🎯 Ruby-idiomatic API for complex LLM workflows
|
|
60
78
|
|
|
61
|
-
class
|
|
79
|
+
class ConfidenceLevel < T::Enum
|
|
62
80
|
enums do
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
# Low confidence, requires further verification
|
|
82
|
+
Low = new('low')
|
|
83
|
+
# High confidence, strongly supported by multiple sources
|
|
84
|
+
High = new('high')
|
|
65
85
|
end
|
|
66
86
|
end
|
|
67
87
|
|
|
68
|
-
class
|
|
69
|
-
|
|
70
|
-
const :
|
|
71
|
-
|
|
88
|
+
class ResearchFindings < T::Struct
|
|
89
|
+
# Detailed findings and analysis results
|
|
90
|
+
const :findings, String
|
|
91
|
+
# Key actionable insights extracted
|
|
92
|
+
const :key_insights, T::Array[String]
|
|
93
|
+
# Assessment of evidence quality and reliability
|
|
94
|
+
const :evidence_quality, ConfidenceLevel
|
|
95
|
+
# Confidence score for the findings (1-10 scale)
|
|
96
|
+
const :confidence_score, Integer
|
|
72
97
|
end
|
|
73
98
|
|
|
74
|
-
class
|
|
75
|
-
|
|
76
|
-
const :
|
|
77
|
-
|
|
78
|
-
const :
|
|
79
|
-
|
|
99
|
+
class ResearchSynthesis < T::Struct
|
|
100
|
+
# High-level executive summary of all findings
|
|
101
|
+
const :executive_summary, String
|
|
102
|
+
# Primary conclusions drawn from the research
|
|
103
|
+
const :key_conclusions, T::Array[String]
|
|
104
|
+
# Collection of research findings
|
|
105
|
+
const :findings_collection, T::Array[ResearchFindings]
|
|
80
106
|
end
|
|
81
107
|
|
|
82
108
|
# Convert with smart defaults (dependencies + descriptions included!)
|
|
83
|
-
|
|
84
|
-
Status.to_baml
|
|
85
|
-
Address.to_baml
|
|
109
|
+
ResearchSynthesis.to_baml
|
|
86
110
|
|
|
87
111
|
# 🚀 Smart defaults include dependencies and descriptions automatically
|
|
88
112
|
# =>
|
|
89
|
-
# enum
|
|
90
|
-
# "
|
|
91
|
-
# "
|
|
113
|
+
# enum ConfidenceLevel {
|
|
114
|
+
# "low" @description("Low confidence, requires further verification")
|
|
115
|
+
# "high" @description("High confidence, strongly supported by multiple sources")
|
|
92
116
|
# }
|
|
93
117
|
#
|
|
94
|
-
# class
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
#
|
|
118
|
+
# class ResearchFindings {
|
|
119
|
+
# findings string @description("Detailed findings and analysis results")
|
|
120
|
+
# key_insights string[] @description("Key actionable insights extracted")
|
|
121
|
+
# evidence_quality ConfidenceLevel @description("Assessment of evidence quality and reliability")
|
|
122
|
+
# confidence_score int @description("Confidence score for the findings (1-10 scale)")
|
|
98
123
|
# }
|
|
99
124
|
#
|
|
100
|
-
# class
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
# tags string[]
|
|
105
|
-
# metadata map<string, string | int>
|
|
125
|
+
# class ResearchSynthesis {
|
|
126
|
+
# executive_summary string @description("High-level executive summary of all findings")
|
|
127
|
+
# key_conclusions string[] @description("Primary conclusions drawn from the research")
|
|
128
|
+
# findings_collection ResearchFindings[] @description("Collection of research findings")
|
|
106
129
|
# }
|
|
107
130
|
|
|
108
131
|
# 🎯 Disable features if needed
|
|
109
|
-
|
|
110
|
-
|
|
132
|
+
ResearchSynthesis.to_baml(include_descriptions: false)
|
|
133
|
+
ResearchSynthesis.to_baml(include_dependencies: false)
|
|
111
134
|
|
|
112
135
|
# 🚀 Customize formatting (smart defaults still apply)
|
|
113
|
-
|
|
136
|
+
ResearchSynthesis.to_baml(indent_size: 4)
|
|
114
137
|
|
|
115
138
|
# Legacy API (no smart defaults, for backwards compatibility)
|
|
116
|
-
SorbetBaml.from_struct(
|
|
117
|
-
SorbetBaml.from_structs([
|
|
139
|
+
SorbetBaml.from_struct(ResearchSynthesis)
|
|
140
|
+
SorbetBaml.from_structs([ResearchSynthesis, ResearchFindings])
|
|
118
141
|
```
|
|
119
142
|
|
|
120
|
-
## 🎯 Field Descriptions
|
|
143
|
+
## 🎯 Field Descriptions for LLM Context
|
|
121
144
|
|
|
122
|
-
Add context to your BAML types by documenting fields with comments:
|
|
145
|
+
Add crucial context to your BAML types by documenting fields with comments - essential for autonomous agents and complex workflows:
|
|
123
146
|
|
|
124
147
|
```ruby
|
|
125
|
-
class
|
|
126
|
-
# User's full legal name for display
|
|
127
|
-
const :name, String
|
|
128
|
-
|
|
129
|
-
# Age in years, must be 18+
|
|
130
|
-
const :age, Integer
|
|
131
|
-
|
|
132
|
-
# Primary email for notifications
|
|
133
|
-
const :email, T.nilable(String)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
class Status < T::Enum
|
|
148
|
+
class TaskType < T::Enum
|
|
137
149
|
enums do
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
# Literature review and information gathering
|
|
151
|
+
Research = new('research')
|
|
152
|
+
# Combining multiple sources into coherent insights
|
|
153
|
+
Synthesis = new('synthesis')
|
|
154
|
+
# Evaluating options or making recommendations
|
|
155
|
+
Evaluation = new('evaluation')
|
|
143
156
|
end
|
|
144
157
|
end
|
|
145
158
|
|
|
159
|
+
class ResearchSubtask < T::Struct
|
|
160
|
+
# Clear description of the specific research objective
|
|
161
|
+
const :objective, String
|
|
162
|
+
|
|
163
|
+
# Type of research task to be performed
|
|
164
|
+
const :task_type, TaskType
|
|
165
|
+
|
|
166
|
+
# Strategic priority ranking for task sequencing (1-5 scale)
|
|
167
|
+
const :priority, Integer
|
|
168
|
+
|
|
169
|
+
# Estimated effort required in hours
|
|
170
|
+
const :estimated_hours, Integer
|
|
171
|
+
|
|
172
|
+
# Suggested agent capabilities needed for optimal execution
|
|
173
|
+
const :required_capabilities, T::Array[String]
|
|
174
|
+
end
|
|
175
|
+
|
|
146
176
|
# Generate BAML (descriptions included by default!)
|
|
147
|
-
|
|
177
|
+
ResearchSubtask.to_baml
|
|
148
178
|
# =>
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
179
|
+
# enum TaskType {
|
|
180
|
+
# "research" @description("Literature review and information gathering")
|
|
181
|
+
# "synthesis" @description("Combining multiple sources into coherent insights")
|
|
182
|
+
# "evaluation" @description("Evaluating options or making recommendations")
|
|
153
183
|
# }
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
#
|
|
184
|
+
#
|
|
185
|
+
# class ResearchSubtask {
|
|
186
|
+
# objective string @description("Clear description of the specific research objective")
|
|
187
|
+
# task_type TaskType @description("Type of research task to be performed")
|
|
188
|
+
# priority int @description("Strategic priority ranking for task sequencing (1-5 scale)")
|
|
189
|
+
# estimated_hours int @description("Estimated effort required in hours")
|
|
190
|
+
# required_capabilities string[] @description("Suggested agent capabilities needed for optimal execution")
|
|
160
191
|
# }
|
|
161
192
|
```
|
|
162
193
|
|
|
@@ -218,53 +249,65 @@ Status.to_baml
|
|
|
218
249
|
|
|
219
250
|
## 🏁 Production Ready
|
|
220
251
|
|
|
221
|
-
This gem has reached **feature completeness** for core BAML conversion needs. The Ruby-idiomatic API is stable and thoroughly tested with **
|
|
252
|
+
This gem has reached **feature completeness** for core BAML conversion needs. The Ruby-idiomatic API is stable and thoroughly tested with **50+ test cases** covering all type combinations and edge cases.
|
|
222
253
|
|
|
223
254
|
### 📊 Quality Metrics
|
|
224
255
|
|
|
225
256
|
- ✅ **100% Test Coverage** - All features comprehensively tested
|
|
226
257
|
- ✅ **Full Sorbet Type Safety** - Zero type errors throughout codebase
|
|
227
|
-
- ✅ **
|
|
258
|
+
- ✅ **50+ Test Cases** - Covering basic types, complex combinations, and edge cases
|
|
228
259
|
- ✅ **TDD Development** - All features built test-first
|
|
260
|
+
- ✅ **Field Descriptions** - Automatic comment extraction for LLM context
|
|
261
|
+
- ✅ **Smart Defaults** - Dependencies and descriptions included by default
|
|
229
262
|
- ✅ **Zero Breaking Changes** - Maintains backward compatibility
|
|
230
263
|
|
|
231
|
-
###
|
|
264
|
+
### ✅ Complete Feature Set
|
|
232
265
|
|
|
233
|
-
|
|
266
|
+
- ✅ **Ruby-idiomatic API**: Every T::Struct and T::Enum gets `.to_baml` method
|
|
267
|
+
- ✅ **Smart defaults**: Field descriptions and dependencies included automatically
|
|
268
|
+
- ✅ **Field descriptions**: Extract documentation from comments for LLM context
|
|
269
|
+
- ✅ **Dependency management**: Automatically includes all referenced types
|
|
270
|
+
- ✅ **Proper ordering**: Dependencies are sorted topologically
|
|
271
|
+
- ✅ **Type safety**: Full Sorbet type checking throughout
|
|
272
|
+
|
|
273
|
+
### 🗺️ Future Enhancements (Optional)
|
|
234
274
|
|
|
235
275
|
- [ ] **Type aliases**: `T.type_alias { String }` → `type Alias = string`
|
|
236
|
-
- [ ] **Field descriptions**: Extract documentation from comments
|
|
237
276
|
- [ ] **Custom naming**: Convert between snake_case ↔ camelCase
|
|
238
|
-
- [ ] **CLI tool**: `sorbet-baml convert
|
|
277
|
+
- [ ] **CLI tool**: `sorbet-baml convert MyStruct` command
|
|
239
278
|
- [ ] **Validation**: Verify generated BAML syntax
|
|
240
279
|
- [ ] **Self-referential types**: `Employee` with `manager: T.nilable(Employee)`
|
|
241
280
|
|
|
242
281
|
### 📈 Version History
|
|
243
282
|
|
|
244
283
|
- **v0.0.1** - Initial implementation with basic type support
|
|
245
|
-
- **v0.1.0**
|
|
284
|
+
- **v0.1.0** - Complete type system + Ruby-idiomatic API + field descriptions + smart defaults
|
|
246
285
|
|
|
247
|
-
## 🌟 Real-World Usage
|
|
286
|
+
## 🌟 Real-World Usage: Autonomous Research Agents
|
|
248
287
|
|
|
249
|
-
Perfect for
|
|
288
|
+
Perfect for agentic workflows, deep research systems, and complex LLM applications:
|
|
250
289
|
|
|
251
290
|
```ruby
|
|
252
|
-
#
|
|
253
|
-
class
|
|
254
|
-
# Your
|
|
291
|
+
# Define your autonomous research workflow types
|
|
292
|
+
class TaskDecomposition < T::Struct
|
|
293
|
+
# Your complex research schema...
|
|
255
294
|
end
|
|
256
295
|
|
|
257
|
-
# Generate BAML for LLM
|
|
296
|
+
# Generate BAML for LLM agents
|
|
258
297
|
prompt = <<~PROMPT
|
|
259
|
-
|
|
298
|
+
You are an autonomous research agent. Analyze this topic and decompose it into strategic subtasks.
|
|
260
299
|
|
|
261
|
-
|
|
300
|
+
Schema for your output:
|
|
301
|
+
#{TaskDecomposition.to_baml}
|
|
262
302
|
|
|
263
|
-
|
|
303
|
+
Topic: "Impact of AI on healthcare delivery systems"
|
|
304
|
+
|
|
305
|
+
Provide a comprehensive task decomposition in JSON format.
|
|
264
306
|
PROMPT
|
|
265
307
|
|
|
266
308
|
# Use with OpenAI, Anthropic, or any LLM provider
|
|
267
|
-
response =
|
|
309
|
+
response = llm_client.chat(prompt)
|
|
310
|
+
result = TaskDecomposition.from_json(response.content)
|
|
268
311
|
```
|
|
269
312
|
|
|
270
313
|
## 🔗 Integration Examples
|
|
@@ -292,43 +335,65 @@ api_types = [User, Order, Product].map(&:to_baml).join("\n\n")
|
|
|
292
335
|
|
|
293
336
|
Here's a real-world comparison using a complex agentic workflow from production DSPy.rb usage:
|
|
294
337
|
|
|
295
|
-
### Complex T::Struct Types (
|
|
338
|
+
### Complex T::Struct Types (Production Agentic Workflow)
|
|
296
339
|
|
|
297
340
|
```ruby
|
|
341
|
+
# Real autonomous research workflow from production DSPy.rb usage
|
|
298
342
|
class ComplexityLevel < T::Enum
|
|
299
343
|
enums do
|
|
344
|
+
# Basic analysis requiring straightforward research
|
|
300
345
|
Basic = new('basic')
|
|
346
|
+
# Intermediate analysis requiring synthesis of multiple sources
|
|
301
347
|
Intermediate = new('intermediate')
|
|
348
|
+
# Advanced analysis requiring deep domain expertise and complex reasoning
|
|
302
349
|
Advanced = new('advanced')
|
|
303
350
|
end
|
|
304
351
|
end
|
|
305
352
|
|
|
306
353
|
class TaskDecomposition < T::Struct
|
|
307
|
-
|
|
354
|
+
# The main research topic being investigated
|
|
355
|
+
const :research_topic, String
|
|
356
|
+
# Additional context or constraints for the research
|
|
308
357
|
const :context, String
|
|
358
|
+
# Target complexity level for the decomposition
|
|
309
359
|
const :complexity_level, ComplexityLevel
|
|
360
|
+
# Autonomously generated list of research subtasks
|
|
310
361
|
const :subtasks, T::Array[String]
|
|
362
|
+
# Type classification for each task (analysis, synthesis, investigation, etc.)
|
|
311
363
|
const :task_types, T::Array[String]
|
|
364
|
+
# Strategic priority rankings (1-5 scale) for each subtask
|
|
312
365
|
const :priority_order, T::Array[Integer]
|
|
366
|
+
# Effort estimates in hours for each subtask
|
|
313
367
|
const :estimated_effort, T::Array[Integer]
|
|
368
|
+
# Task dependency relationships for optimal sequencing
|
|
314
369
|
const :dependencies, T::Array[String]
|
|
370
|
+
# Suggested agent types/skills needed for each task
|
|
315
371
|
const :agent_requirements, T::Array[String]
|
|
316
372
|
end
|
|
317
373
|
|
|
318
374
|
class ResearchExecution < T::Struct
|
|
375
|
+
# The specific research subtask to execute
|
|
319
376
|
const :subtask, String
|
|
377
|
+
# Accumulated context from previous research steps
|
|
320
378
|
const :context, String
|
|
379
|
+
# Any specific constraints or focus areas for this research
|
|
321
380
|
const :constraints, String
|
|
381
|
+
# Detailed research findings and analysis
|
|
322
382
|
const :findings, String
|
|
383
|
+
# Key actionable insights extracted from the research
|
|
323
384
|
const :key_insights, T::Array[String]
|
|
385
|
+
# Confidence in findings quality (1-10 scale)
|
|
324
386
|
const :confidence_level, Integer
|
|
387
|
+
# Assessment of evidence quality and reliability
|
|
325
388
|
const :evidence_quality, String
|
|
389
|
+
# Recommended next steps based on these findings
|
|
326
390
|
const :next_steps, T::Array[String]
|
|
391
|
+
# Identified gaps in knowledge or areas needing further research
|
|
327
392
|
const :knowledge_gaps, T::Array[String]
|
|
328
393
|
end
|
|
329
394
|
```
|
|
330
395
|
|
|
331
|
-
### 📊 **BAML Output (Ruby-idiomatic)**
|
|
396
|
+
### 📊 **BAML Output (Ruby-idiomatic with descriptions)**
|
|
332
397
|
|
|
333
398
|
```ruby
|
|
334
399
|
[ComplexityLevel, TaskDecomposition, ResearchExecution].map(&:to_baml).join("\n\n")
|
|
@@ -336,37 +401,37 @@ end
|
|
|
336
401
|
|
|
337
402
|
```baml
|
|
338
403
|
enum ComplexityLevel {
|
|
339
|
-
"basic"
|
|
340
|
-
"intermediate"
|
|
341
|
-
"advanced"
|
|
404
|
+
"basic" @description("Basic analysis requiring straightforward research")
|
|
405
|
+
"intermediate" @description("Intermediate analysis requiring synthesis of multiple sources")
|
|
406
|
+
"advanced" @description("Advanced analysis requiring deep domain expertise and complex reasoning")
|
|
342
407
|
}
|
|
343
408
|
|
|
344
409
|
class TaskDecomposition {
|
|
345
|
-
topic
|
|
346
|
-
context string
|
|
347
|
-
complexity_level ComplexityLevel
|
|
348
|
-
subtasks string[]
|
|
349
|
-
task_types string[]
|
|
350
|
-
priority_order int[]
|
|
351
|
-
estimated_effort int[]
|
|
352
|
-
dependencies string[]
|
|
353
|
-
agent_requirements string[]
|
|
410
|
+
research_topic string @description("The main research topic being investigated")
|
|
411
|
+
context string @description("Additional context or constraints for the research")
|
|
412
|
+
complexity_level ComplexityLevel @description("Target complexity level for the decomposition")
|
|
413
|
+
subtasks string[] @description("Autonomously generated list of research subtasks")
|
|
414
|
+
task_types string[] @description("Type classification for each task (analysis, synthesis, investigation, etc.)")
|
|
415
|
+
priority_order int[] @description("Strategic priority rankings (1-5 scale) for each subtask")
|
|
416
|
+
estimated_effort int[] @description("Effort estimates in hours for each subtask")
|
|
417
|
+
dependencies string[] @description("Task dependency relationships for optimal sequencing")
|
|
418
|
+
agent_requirements string[] @description("Suggested agent types/skills needed for each task")
|
|
354
419
|
}
|
|
355
420
|
|
|
356
421
|
class ResearchExecution {
|
|
357
|
-
subtask string
|
|
358
|
-
context string
|
|
359
|
-
constraints string
|
|
360
|
-
findings string
|
|
361
|
-
key_insights string[]
|
|
362
|
-
confidence_level int
|
|
363
|
-
evidence_quality string
|
|
364
|
-
next_steps string[]
|
|
365
|
-
knowledge_gaps string[]
|
|
422
|
+
subtask string @description("The specific research subtask to execute")
|
|
423
|
+
context string @description("Accumulated context from previous research steps")
|
|
424
|
+
constraints string @description("Any specific constraints or focus areas for this research")
|
|
425
|
+
findings string @description("Detailed research findings and analysis")
|
|
426
|
+
key_insights string[] @description("Key actionable insights extracted from the research")
|
|
427
|
+
confidence_level int @description("Confidence in findings quality (1-10 scale)")
|
|
428
|
+
evidence_quality string @description("Assessment of evidence quality and reliability")
|
|
429
|
+
next_steps string[] @description("Recommended next steps based on these findings")
|
|
430
|
+
knowledge_gaps string[] @description("Identified gaps in knowledge or areas needing further research")
|
|
366
431
|
}
|
|
367
432
|
```
|
|
368
433
|
|
|
369
|
-
**BAML Token Count: ~
|
|
434
|
+
**BAML Token Count: ~320 tokens**
|
|
370
435
|
|
|
371
436
|
### 📊 **JSON Schema Equivalent**
|
|
372
437
|
|
|
@@ -439,22 +504,29 @@ class ResearchExecution {
|
|
|
439
504
|
}
|
|
440
505
|
```
|
|
441
506
|
|
|
442
|
-
**JSON Schema Token Count: ~
|
|
507
|
+
**JSON Schema Token Count: ~680 tokens**
|
|
508
|
+
|
|
509
|
+
### 🎯 **Results: 53% Token Reduction (with descriptions)**
|
|
443
510
|
|
|
444
|
-
|
|
511
|
+
| Format | Tokens | Reduction |
|
|
512
|
+
|--------|--------|-----------|
|
|
513
|
+
| JSON Schema | ~680 | baseline |
|
|
514
|
+
| **BAML** | **~320** | **🔥 53% fewer** |
|
|
445
515
|
|
|
516
|
+
**Without descriptions:**
|
|
446
517
|
| Format | Tokens | Reduction |
|
|
447
518
|
|--------|--------|-----------|
|
|
448
519
|
| JSON Schema | ~450 | baseline |
|
|
449
520
|
| **BAML** | **~180** | **🔥 60% fewer** |
|
|
450
521
|
|
|
451
522
|
**Real Impact:**
|
|
452
|
-
- **Cost Savings**: 60% reduction in prompt tokens =
|
|
523
|
+
- **Cost Savings**: 53-60% reduction in prompt tokens = significant LLM API cost savings
|
|
453
524
|
- **Performance**: Smaller prompts = faster LLM response times
|
|
454
525
|
- **Context Efficiency**: More room for actual content vs. type definitions
|
|
526
|
+
- **LLM Understanding**: Descriptions provide crucial context for autonomous agents
|
|
455
527
|
- **Readability**: BAML is human-readable and maintainable
|
|
456
528
|
|
|
457
|
-
*This example represents actual agentic workflows from production DSPy.rb applications using complex nested types, enums, and arrays - exactly the scenarios where token efficiency
|
|
529
|
+
*This example represents actual agentic workflows from production DSPy.rb applications using complex nested types, enums, and arrays - exactly the scenarios where token efficiency and LLM understanding matter most.*
|
|
458
530
|
|
|
459
531
|
## Credits
|
|
460
532
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# typed: false
|
|
3
|
+
|
|
4
|
+
require_relative '../lib/sorbet_baml'
|
|
5
|
+
|
|
6
|
+
puts "🎯 Description Parameter Support Demo"
|
|
7
|
+
puts "=" * 50
|
|
8
|
+
|
|
9
|
+
# Example 1: Basic description parameters
|
|
10
|
+
class User < T::Struct
|
|
11
|
+
const :name, String, description: "User's full legal name"
|
|
12
|
+
prop :age, Integer, description: "Age in years"
|
|
13
|
+
const :email, T.nilable(String), description: "Optional email address for notifications"
|
|
14
|
+
const :interests, T::Array[String], description: "List of user hobbies and interests"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
puts "\n1. Basic T::Struct with description parameters:"
|
|
18
|
+
puts User.to_baml
|
|
19
|
+
|
|
20
|
+
# Example 2: Mixed description sources (parameters + comments)
|
|
21
|
+
class Product < T::Struct
|
|
22
|
+
# This comment will be used as fallback
|
|
23
|
+
const :id, String
|
|
24
|
+
|
|
25
|
+
const :name, String, description: "Product name for display"
|
|
26
|
+
|
|
27
|
+
# Price in USD cents
|
|
28
|
+
prop :price_cents, Integer
|
|
29
|
+
|
|
30
|
+
const :category, String, description: "Product category classification"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
puts "\n2. Mixed description sources (parameters take priority):"
|
|
34
|
+
puts Product.to_baml
|
|
35
|
+
|
|
36
|
+
# Example 3: Complex nested types with descriptions
|
|
37
|
+
class Order < T::Struct
|
|
38
|
+
const :id, String, description: "Unique order identifier"
|
|
39
|
+
const :customer, User, description: "Customer who placed the order"
|
|
40
|
+
const :items, T::Array[Product], description: "List of ordered products"
|
|
41
|
+
const :total_cents, Integer, description: "Total order value in USD cents"
|
|
42
|
+
const :status, String, description: "Current order processing status"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
puts "\n3. Complex nested types with dependencies:"
|
|
46
|
+
puts Order.to_baml
|
|
47
|
+
|
|
48
|
+
puts "\n✨ Beautiful, readable, and LLM-friendly!"
|
|
49
|
+
puts "🚀 Perfect for DSPy.rb, autonomous agents, and structured LLM outputs"
|