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.
@@ -1,427 +0,0 @@
1
- # Advanced Usage
2
-
3
- ## Ruby-Idiomatic API
4
-
5
- The gem automatically extends all T::Struct and T::Enum classes with conversion methods:
6
-
7
- ```ruby
8
- class User < T::Struct
9
- const :name, String
10
- const :age, Integer
11
- end
12
-
13
- # Ruby-idiomatic - just call the method!
14
- User.to_baml
15
- User.baml_type_definition # Same as to_baml
16
- ```
17
-
18
- ## Automatic Dependency Management
19
-
20
- The most powerful feature is automatic dependency resolution:
21
-
22
- ```ruby
23
- class ContactInfo < T::Struct
24
- const :email, String
25
- const :phone, T.nilable(String)
26
- end
27
-
28
- class Company < T::Struct
29
- const :name, String
30
- const :contact, ContactInfo
31
- end
32
-
33
- class User < T::Struct
34
- const :name, String
35
- const :company, Company
36
- end
37
-
38
- # Dependencies included automatically with smart defaults!
39
- User.to_baml
40
- ```
41
-
42
- **Generated BAML (with correct ordering):**
43
- ```baml
44
- class ContactInfo {
45
- email string
46
- phone string?
47
- }
48
-
49
- class Company {
50
- name string
51
- contact ContactInfo
52
- }
53
-
54
- class User {
55
- name string
56
- company Company
57
- }
58
- ```
59
-
60
- ## Converting Multiple Types
61
-
62
- ### Manual Collection
63
-
64
- ```ruby
65
- # Convert multiple types manually
66
- types = [ContactInfo, Company, User]
67
- baml_output = types.map(&:to_baml).join("\n\n")
68
- ```
69
-
70
- ### Legacy API (still supported)
71
-
72
- ```ruby
73
- # Legacy API for multiple structs
74
- SorbetBaml.from_structs([ContactInfo, Company, User])
75
-
76
- # Legacy API for single struct
77
- SorbetBaml.from_struct(User)
78
- ```
79
-
80
- ## Advanced Type Examples
81
-
82
- ### Complex Enums with Structs
83
-
84
- ```ruby
85
- class OrderStatus < T::Enum
86
- enums do
87
- Pending = new('pending')
88
- Processing = new('processing')
89
- Shipped = new('shipped')
90
- Delivered = new('delivered')
91
- Cancelled = new('cancelled')
92
- end
93
- end
94
-
95
- class OrderItem < T::Struct
96
- const :product_id, String
97
- const :quantity, Integer
98
- const :price, Float
99
- end
100
-
101
- class Order < T::Struct
102
- const :id, String
103
- const :status, OrderStatus
104
- const :items, T::Array[OrderItem]
105
- const :metadata, T::Hash[String, T.any(String, Integer, Float)]
106
- const :shipping_address, T.nilable(Address)
107
- end
108
-
109
- # Generate complete type definitions
110
- [OrderStatus, OrderItem, Order].map(&:to_baml).join("\n\n")
111
- ```
112
-
113
- **Generated BAML:**
114
- ```baml
115
- enum OrderStatus {
116
- "pending"
117
- "processing"
118
- "shipped"
119
- "delivered"
120
- "cancelled"
121
- }
122
-
123
- class OrderItem {
124
- product_id string
125
- quantity int
126
- price float
127
- }
128
-
129
- class Order {
130
- id string
131
- status OrderStatus
132
- items OrderItem[]
133
- metadata map<string, string | int | float>
134
- shipping_address Address?
135
- }
136
- ```
137
-
138
- ### Self-Referential Types
139
-
140
- ```ruby
141
- class Category < T::Struct
142
- const :name, String
143
- const :parent, T.nilable(Category)
144
- const :children, T::Array[Category]
145
- end
146
-
147
- Category.to_baml
148
- ```
149
-
150
- **Generated BAML:**
151
- ```baml
152
- class Category {
153
- name string
154
- parent Category?
155
- children Category[]
156
- }
157
- ```
158
-
159
- ## Configuration Options
160
-
161
- ### Custom Indentation
162
-
163
- ```ruby
164
- User.to_baml(indent_size: 4)
165
- ```
166
-
167
- **Generated BAML:**
168
- ```baml
169
- class User {
170
- name string
171
- age int
172
- }
173
- ```
174
-
175
- ### Field Descriptions
176
-
177
- Extract documentation from Ruby comments to provide LLM context:
178
-
179
- ```ruby
180
- class DocumentedUser < T::Struct
181
- # User's full legal name for official records
182
- const :full_name, String
183
-
184
- # Age in years, must be 18 or older for account creation
185
- const :age, Integer
186
-
187
- # Primary email address for account notifications
188
- const :email, String
189
- end
190
-
191
- DocumentedUser.to_baml
192
- ```
193
-
194
- **Generated BAML with descriptions:**
195
- ```baml
196
- class DocumentedUser {
197
- full_name string @description("User's full legal name for official records")
198
- age int @description("Age in years, must be 18 or older for account creation")
199
- email string @description("Primary email address for account notifications")
200
- }
201
- ```
202
-
203
- ### Combining Options
204
-
205
- ```ruby
206
- # Smart defaults: dependencies and descriptions already included!
207
- User.to_baml(indent_size: 4)
208
-
209
- # Or disable features if needed
210
- User.to_baml(
211
- include_dependencies: false,
212
- include_descriptions: false,
213
- indent_size: 4
214
- )
215
- ```
216
-
217
- ## File Generation
218
-
219
- ### Single File Output
220
-
221
- ```ruby
222
- # Generate and write to file (dependencies included by default)
223
- baml_content = User.to_baml
224
- File.write("types/user.baml", baml_content)
225
- ```
226
-
227
- ### Multiple Files
228
-
229
- ```ruby
230
- # Generate separate files for each type
231
- [User, Company, ContactInfo].each do |type|
232
- filename = type.name.downcase.gsub('::', '_')
233
- File.write("types/#{filename}.baml", type.to_baml)
234
- end
235
- ```
236
-
237
- ### Build Process Integration
238
-
239
- ```ruby
240
- # Rakefile
241
- desc "Generate BAML type definitions"
242
- task :generate_baml do
243
- require 'sorbet-baml'
244
- require_relative 'app/models'
245
-
246
- types = [User, Company, Order, Product] # Your app types
247
- baml_content = types.map(&:to_baml).join("\n\n")
248
-
249
- File.write("lib/types.baml", baml_content)
250
- puts "Generated BAML types in lib/types.baml"
251
- end
252
- ```
253
-
254
- ## LLM Integration Patterns
255
-
256
- ### With OpenAI Structured Outputs
257
-
258
- ```ruby
259
- require 'openai'
260
- require 'sorbet-baml'
261
-
262
- # Define your response format
263
- class AnalysisResult < T::Struct
264
- const :sentiment, String
265
- const :confidence, Float
266
- const :key_phrases, T::Array[String]
267
- const :metadata, T::Hash[String, String]
268
- end
269
-
270
- # Generate schema for LLM
271
- schema = AnalysisResult.to_baml
272
-
273
- client = OpenAI::Client.new
274
- response = client.chat(
275
- parameters: {
276
- model: "gpt-4o",
277
- messages: [
278
- {
279
- role: "system",
280
- content: "Analyze text and respond with data matching this BAML schema:\n\n#{schema}"
281
- },
282
- {
283
- role: "user",
284
- content: "Analyze: 'I love this new product!'"
285
- }
286
- ]
287
- }
288
- )
289
- ```
290
-
291
- ### With Anthropic Claude
292
-
293
- ```ruby
294
- require 'anthropic'
295
- require 'sorbet-baml'
296
-
297
- schema = UserProfile.to_baml(include_dependencies: true)
298
-
299
- client = Anthropic::Client.new
300
- response = client.messages(
301
- model: "claude-3-5-sonnet-20241022",
302
- max_tokens: 1000,
303
- messages: [
304
- {
305
- role: "user",
306
- content: "Generate a realistic user profile matching this schema:\n\n#{schema}"
307
- }
308
- ]
309
- )
310
- ```
311
-
312
- ### With DSPy.rb Integration
313
-
314
- ```ruby
315
- require 'dspy'
316
- require 'sorbet-baml'
317
-
318
- # Your T::Struct automatically works with DSPy signatures
319
- class UserAnalysis < DSPy::Signature
320
- input { const :user_data, String }
321
- output { const :analysis, AnalysisResult } # Uses your T::Struct
322
- end
323
-
324
- # The BAML schema is automatically generated for LLM prompts
325
- predictor = DSPy::Predict.new(UserAnalysis)
326
- result = predictor.call(user_data: "John, 25, loves hiking")
327
- ```
328
-
329
- ### Prompt Engineering
330
-
331
- ```ruby
332
- # Template for complex prompts
333
- def build_analysis_prompt(data, schema)
334
- <<~PROMPT
335
- You are a data analyst. Analyze the following data and return results
336
- in the exact format specified by this BAML schema:
337
-
338
- #{schema}
339
-
340
- Data to analyze:
341
- #{data}
342
-
343
- Requirements:
344
- - Follow the schema exactly
345
- - Provide confidence scores between 0.0 and 1.0
346
- - Extract meaningful insights
347
- PROMPT
348
- end
349
-
350
- schema = AnalysisResult.to_baml
351
- prompt = build_analysis_prompt(user_input, schema)
352
- ```
353
-
354
- ## Rails Integration
355
-
356
- ### Model Integration
357
-
358
- ```ruby
359
- # app/models/user.rb
360
- class User < ApplicationRecord
361
- # Your ActiveRecord model...
362
-
363
- # Add Sorbet types for API schemas
364
- class UserAPI < T::Struct
365
- const :id, Integer
366
- const :name, String
367
- const :email, String
368
- const :created_at, String
369
- end
370
-
371
- def to_api_schema
372
- UserAPI.to_baml
373
- end
374
- end
375
-
376
- # Usage in controllers
377
- class UsersController < ApplicationController
378
- def schema
379
- render json: { schema: User::UserAPI.to_baml }
380
- end
381
- end
382
- ```
383
-
384
- ### API Documentation
385
-
386
- ```ruby
387
- # Generate API docs automatically
388
- class ApiDocsGenerator
389
- API_TYPES = [
390
- User::UserAPI,
391
- Order::OrderAPI,
392
- Product::ProductAPI
393
- ].freeze
394
-
395
- def self.generate
396
- schema = API_TYPES.map(&:to_baml).join("\n\n")
397
- File.write("docs/api_schema.baml", schema)
398
- end
399
- end
400
- ```
401
-
402
- ## Performance Considerations
403
-
404
- ### Caching Generated BAML
405
-
406
- ```ruby
407
- class CachedTypeConverter
408
- def self.to_baml(type)
409
- @cache ||= {}
410
- @cache[type] ||= type.to_baml
411
- end
412
- end
413
-
414
- # Use in production for frequently accessed types
415
- schema = CachedTypeConverter.to_baml(User)
416
- ```
417
-
418
- ### Lazy Loading
419
-
420
- ```ruby
421
- # Only generate BAML when needed (smart defaults apply)
422
- class ApiResponse
423
- def schema
424
- @schema ||= self.class.to_baml
425
- end
426
- end
427
- ```
@@ -1,91 +0,0 @@
1
- # Getting Started
2
-
3
- ## Prerequisites
4
-
5
- - Ruby 3.2+
6
- - Sorbet installed in your project
7
- - Basic familiarity with T::Struct
8
-
9
- ## Quick Start
10
-
11
- ### 1. Define your Sorbet types
12
-
13
- ```ruby
14
- class User < T::Struct
15
- const :id, Integer
16
- const :name, String
17
- const :email, T.nilable(String)
18
- end
19
- ```
20
-
21
- ### 2. Convert to BAML
22
-
23
- ```ruby
24
- require 'sorbet-baml'
25
-
26
- # Ruby-idiomatic API (recommended)
27
- User.to_baml
28
-
29
- # Legacy API (still supported)
30
- baml = SorbetBaml.from_struct(User)
31
- puts baml
32
- ```
33
-
34
- **Generated BAML:**
35
- ```baml
36
- class User {
37
- id int
38
- name string
39
- email string?
40
- }
41
- ```
42
-
43
- ### 3. Add field descriptions (optional)
44
-
45
- Document your fields with comments for better LLM understanding:
46
-
47
- ```ruby
48
- class User < T::Struct
49
- # Unique identifier for the user account
50
- const :id, Integer
51
-
52
- # User's display name, visible to other users
53
- const :name, String
54
-
55
- # Optional email for notifications and login
56
- const :email, T.nilable(String)
57
- end
58
-
59
- # Generate BAML (descriptions included by default!)
60
- User.to_baml
61
- ```
62
-
63
- **Generated BAML with descriptions:**
64
- ```baml
65
- class User {
66
- id int @description("Unique identifier for the user account")
67
- name string @description("User's display name, visible to other users")
68
- email string? @description("Optional email for notifications and login")
69
- }
70
- ```
71
-
72
- ### 4. Use with your LLM
73
-
74
- Include the BAML definition in your prompt:
75
-
76
- ```ruby
77
- baml = User.to_baml
78
- prompt = <<~PROMPT
79
- Generate sample data matching this schema:
80
-
81
- #{baml}
82
-
83
- Return 3 realistic examples.
84
- PROMPT
85
- ```
86
-
87
- ## Next Steps
88
-
89
- - [Type Mapping Reference](./type-mapping.md)
90
- - [Advanced Usage](./advanced-usage.md)
91
- - [Troubleshooting](./troubleshooting.md)