poml 0.0.6 → 0.0.7

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/docs/tutorial/advanced/performance.md +695 -0
  3. data/docs/tutorial/advanced/tool-registration.md +776 -0
  4. data/docs/tutorial/basic-usage.md +351 -0
  5. data/docs/tutorial/components/chat-components.md +552 -0
  6. data/docs/tutorial/components/formatting.md +623 -0
  7. data/docs/tutorial/components/index.md +366 -0
  8. data/docs/tutorial/components/media-components.md +259 -0
  9. data/docs/tutorial/components/schema-components.md +668 -0
  10. data/docs/tutorial/index.md +184 -0
  11. data/docs/tutorial/output-formats.md +688 -0
  12. data/docs/tutorial/quickstart.md +30 -0
  13. data/docs/tutorial/template-engine.md +540 -0
  14. data/lib/poml/components/base.rb +146 -4
  15. data/lib/poml/components/content.rb +10 -3
  16. data/lib/poml/components/data.rb +539 -19
  17. data/lib/poml/components/examples.rb +235 -1
  18. data/lib/poml/components/formatting.rb +184 -18
  19. data/lib/poml/components/layout.rb +7 -2
  20. data/lib/poml/components/lists.rb +69 -35
  21. data/lib/poml/components/meta.rb +134 -5
  22. data/lib/poml/components/output_schema.rb +19 -1
  23. data/lib/poml/components/template.rb +72 -61
  24. data/lib/poml/components/text.rb +30 -1
  25. data/lib/poml/components/tool.rb +81 -0
  26. data/lib/poml/components/tool_definition.rb +339 -10
  27. data/lib/poml/components/tools.rb +14 -0
  28. data/lib/poml/components/utilities.rb +34 -18
  29. data/lib/poml/components.rb +19 -0
  30. data/lib/poml/context.rb +19 -4
  31. data/lib/poml/parser.rb +88 -63
  32. data/lib/poml/renderer.rb +191 -9
  33. data/lib/poml/template_engine.rb +138 -13
  34. data/lib/poml/version.rb +1 -1
  35. data/lib/poml.rb +16 -1
  36. data/readme.md +154 -27
  37. metadata +31 -4
  38. data/TUTORIAL.md +0 -987
@@ -0,0 +1,540 @@
1
+ # Template Engine
2
+
3
+ POML includes a powerful template engine that supports variables, conditionals, loops, and meta variables for creating dynamic, reusable prompts.
4
+
5
+ ## Variable Substitution
6
+
7
+ ### Basic Variables
8
+
9
+ Use `{{variable_name}}` syntax for simple variable substitution:
10
+
11
+ ```ruby
12
+ require 'poml'
13
+
14
+ markup = <<~POML
15
+ <poml>
16
+ <role>{{expert_type}} Expert</role>
17
+ <task>{{main_task}}</task>
18
+ <hint>Focus on {{focus_area}} and provide {{output_type}}</hint>
19
+ </poml>
20
+ POML
21
+
22
+ context = {
23
+ 'expert_type' => 'Machine Learning',
24
+ 'main_task' => 'Analyze model performance',
25
+ 'focus_area' => 'accuracy metrics',
26
+ 'output_type' => 'actionable recommendations'
27
+ }
28
+
29
+ result = Poml.process(markup: markup, context: context)
30
+ puts result['content']
31
+ ```
32
+
33
+ ### Variable Safety
34
+
35
+ Variables that don't exist in context are left unchanged:
36
+
37
+ ```ruby
38
+ markup = '<poml><role>{{existing}} and {{missing}}</role></poml>'
39
+ context = { 'existing' => 'Data Scientist' }
40
+
41
+ result = Poml.process(markup: markup, context: context)
42
+ # Output will contain: "Data Scientist and {{missing}}"
43
+ ```
44
+
45
+ ## Meta Variables
46
+
47
+ Use the `<meta variables="">` component to define template variables within the POML document:
48
+
49
+ ```ruby
50
+ markup = <<~POML
51
+ <poml>
52
+ <meta variables='{"project": "E-commerce Platform", "deadline": "Q4 2024", "team_size": 8}' />
53
+
54
+ <role>Project Manager</role>
55
+ <task>Create project plan for {{project}}</task>
56
+
57
+ <p>Project Details:</p>
58
+ <list>
59
+ <item>Deadline: {{deadline}}</item>
60
+ <item>Team Size: {{team_size}} developers</item>
61
+ </list>
62
+ </poml>
63
+ POML
64
+
65
+ result = Poml.process(markup: markup)
66
+ puts result['content']
67
+ ```
68
+
69
+ ### Combining Context and Meta Variables
70
+
71
+ External context overrides meta variables:
72
+
73
+ ```ruby
74
+ markup = <<~POML
75
+ <poml>
76
+ <meta variables='{"environment": "development", "debug": true}' />
77
+
78
+ <role>DevOps Engineer</role>
79
+ <task>Deploy to {{environment}} environment</task>
80
+ <hint>Debug mode: {{debug}}</hint>
81
+ </poml>
82
+ POML
83
+
84
+ # Override meta variables
85
+ context = { 'environment' => 'production', 'debug' => false }
86
+
87
+ result = Poml.process(markup: markup, context: context)
88
+ # Will use production/false instead of development/true
89
+ ```
90
+
91
+ ## Conditional Logic
92
+
93
+ ### Basic If Statements
94
+
95
+ Use `<if condition="">` for conditional content:
96
+
97
+ ```ruby
98
+ markup = <<~POML
99
+ <poml>
100
+ <role>Security Analyst</role>
101
+ <task>Analyze security requirements</task>
102
+
103
+ <if condition="{{security_level}} == 'high'">
104
+ <p>Implement additional security measures:</p>
105
+ <list>
106
+ <item>Multi-factor authentication</item>
107
+ <item>End-to-end encryption</item>
108
+ <item>Regular security audits</item>
109
+ </list>
110
+ </if>
111
+
112
+ <if condition="{{compliance_required}}">
113
+ <p>Ensure compliance with {{compliance_standards}}.</p>
114
+ </if>
115
+ </poml>
116
+ POML
117
+
118
+ context = {
119
+ 'security_level' => 'high',
120
+ 'compliance_required' => true,
121
+ 'compliance_standards' => 'SOC 2 and GDPR'
122
+ }
123
+
124
+ result = Poml.process(markup: markup, context: context)
125
+ ```
126
+
127
+ ### Comparison Operators
128
+
129
+ POML supports various comparison operators:
130
+
131
+ ```ruby
132
+ markup = <<~POML
133
+ <poml>
134
+ <role>Performance Analyst</role>
135
+ <task>Analyze performance metrics</task>
136
+
137
+ <if condition="{{response_time}} > 500">
138
+ <p>⚠️ Response time is too slow: {{response_time}}ms</p>
139
+ </if>
140
+
141
+ <if condition="{{cpu_usage}} >= 80">
142
+ <p>🔥 High CPU usage detected: {{cpu_usage}}%</p>
143
+ </if>
144
+
145
+ <if condition="{{error_rate}} <= 0.1">
146
+ <p>✅ Error rate is acceptable: {{error_rate}}%</p>
147
+ </if>
148
+
149
+ <if condition="{{environment}} != 'production'">
150
+ <p>🚧 Non-production environment: {{environment}}</p>
151
+ </if>
152
+ </poml>
153
+ POML
154
+
155
+ context = {
156
+ 'response_time' => 750,
157
+ 'cpu_usage' => 85,
158
+ 'error_rate' => 0.05,
159
+ 'environment' => 'staging'
160
+ }
161
+ ```
162
+
163
+ Supported operators:
164
+
165
+ - `==` - Equal to
166
+ - `!=` - Not equal to
167
+ - `>` - Greater than
168
+ - `>=` - Greater than or equal to
169
+ - `<` - Less than
170
+ - `<=` - Less than or equal to
171
+
172
+ ### Boolean Conditions
173
+
174
+ ```ruby
175
+ markup = <<~POML
176
+ <poml>
177
+ <role>DevOps Engineer</role>
178
+ <task>Configure deployment</task>
179
+
180
+ <if condition="{{enable_monitoring}}">
181
+ <p>Enable monitoring and alerting systems.</p>
182
+ </if>
183
+
184
+ <if condition="!{{debug_mode}}">
185
+ <p>Disable debug logging for production.</p>
186
+ </if>
187
+ </poml>
188
+ POML
189
+
190
+ context = {
191
+ 'enable_monitoring' => true,
192
+ 'debug_mode' => false
193
+ }
194
+ ```
195
+
196
+ ## Loops and Iteration
197
+
198
+ ### Basic For Loops
199
+
200
+ Use `<for variable="" items="">` to iterate over arrays:
201
+
202
+ ```ruby
203
+ markup = <<~POML
204
+ <poml>
205
+ <role>API Documentation Writer</role>
206
+ <task>Document API endpoints</task>
207
+
208
+ <p>Available endpoints:</p>
209
+ <list>
210
+ <for variable="endpoint" items="{{endpoints}}">
211
+ <item><b>{{endpoint.method}} {{endpoint.path}}</b> - {{endpoint.description}}</item>
212
+ </for>
213
+ </list>
214
+ </poml>
215
+ POML
216
+
217
+ context = {
218
+ 'endpoints' => [
219
+ { 'method' => 'GET', 'path' => '/users', 'description' => 'List all users' },
220
+ { 'method' => 'POST', 'path' => '/users', 'description' => 'Create new user' },
221
+ { 'method' => 'PUT', 'path' => '/users/:id', 'description' => 'Update user' },
222
+ { 'method' => 'DELETE', 'path' => '/users/:id', 'description' => 'Delete user' }
223
+ ]
224
+ }
225
+
226
+ result = Poml.process(markup: markup, context: context)
227
+ ```
228
+
229
+ ### Simple Array Iteration
230
+
231
+ For simple arrays, use `{{.}}` to reference the current item:
232
+
233
+ ```ruby
234
+ markup = <<~POML
235
+ <poml>
236
+ <role>Tech Lead</role>
237
+ <task>Review technology stack</task>
238
+
239
+ <p>Current technologies:</p>
240
+ <list>
241
+ <for variable="tech" items="{{technologies}}">
242
+ <item>{{.}}</item>
243
+ </for>
244
+ </list>
245
+ </poml>
246
+ POML
247
+
248
+ context = {
249
+ 'technologies' => ['Ruby on Rails', 'PostgreSQL', 'Redis', 'Docker', 'AWS']
250
+ }
251
+ ```
252
+
253
+ ### Nested Loops
254
+
255
+ ```ruby
256
+ markup = <<~POML
257
+ <poml>
258
+ <role>Test Engineer</role>
259
+ <task>Create test plan</task>
260
+
261
+ <for variable="feature" items="{{features}}">
262
+ <p><b>Feature: {{feature.name}}</b></p>
263
+ <list>
264
+ <for variable="test" items="{{feature.tests}}">
265
+ <item>{{test.type}}: {{test.description}}</item>
266
+ </for>
267
+ </list>
268
+ </for>
269
+ </poml>
270
+ POML
271
+
272
+ context = {
273
+ 'features' => [
274
+ {
275
+ 'name' => 'User Authentication',
276
+ 'tests' => [
277
+ { 'type' => 'Unit', 'description' => 'Test password validation' },
278
+ { 'type' => 'Integration', 'description' => 'Test login flow' }
279
+ ]
280
+ },
281
+ {
282
+ 'name' => 'Data Export',
283
+ 'tests' => [
284
+ { 'type' => 'Unit', 'description' => 'Test CSV generation' },
285
+ { 'type' => 'E2E', 'description' => 'Test complete export workflow' }
286
+ ]
287
+ }
288
+ ]
289
+ }
290
+ ```
291
+
292
+ ## Combining Conditionals and Loops
293
+
294
+ ### Conditional Lists
295
+
296
+ ```ruby
297
+ markup = <<~POML
298
+ <poml>
299
+ <role>Release Manager</role>
300
+ <task>Prepare release notes</task>
301
+
302
+ <if condition="{{bug_fixes}}">
303
+ <p><b>Bug Fixes:</b></p>
304
+ <list>
305
+ <for variable="fix" items="{{bug_fixes}}">
306
+ <item>{{fix.description}} ({{fix.ticket}})</item>
307
+ </for>
308
+ </list>
309
+ </if>
310
+
311
+ <if condition="{{new_features}}">
312
+ <p><b>New Features:</b></p>
313
+ <list>
314
+ <for variable="feature" items="{{new_features}}">
315
+ <item>{{feature.name}} - {{feature.description}}</item>
316
+ </for>
317
+ </list>
318
+ </if>
319
+ </poml>
320
+ POML
321
+
322
+ context = {
323
+ 'bug_fixes' => [
324
+ { 'description' => 'Fixed login timeout issue', 'ticket' => 'BUG-123' },
325
+ { 'description' => 'Resolved data export corruption', 'ticket' => 'BUG-124' }
326
+ ],
327
+ 'new_features' => [
328
+ { 'name' => 'Dark Mode', 'description' => 'Added dark theme support' },
329
+ { 'name' => 'API Rate Limiting', 'description' => 'Implemented request throttling' }
330
+ ]
331
+ }
332
+ ```
333
+
334
+ ### Conditional Content Within Loops
335
+
336
+ ```ruby
337
+ markup = <<~POML
338
+ <poml>
339
+ <role>Code Reviewer</role>
340
+ <task>Review code changes</task>
341
+
342
+ <p>Files Changed:</p>
343
+ <list>
344
+ <for variable="file" items="{{changed_files}}">
345
+ <item>
346
+ <b>{{file.path}}</b>
347
+ <if condition="{{file.lines_added}} > 100">
348
+ ⚠️ Large change: +{{file.lines_added}} lines
349
+ </if>
350
+ <if condition="{{file.complexity}} == 'high'">
351
+ 🔍 High complexity - needs careful review
352
+ </if>
353
+ </item>
354
+ </for>
355
+ </list>
356
+ </poml>
357
+ POML
358
+
359
+ context = {
360
+ 'changed_files' => [
361
+ { 'path' => 'app/models/user.rb', 'lines_added' => 45, 'complexity' => 'medium' },
362
+ { 'path' => 'app/services/payment_processor.rb', 'lines_added' => 150, 'complexity' => 'high' },
363
+ { 'path' => 'config/routes.rb', 'lines_added' => 5, 'complexity' => 'low' }
364
+ ]
365
+ }
366
+ ```
367
+
368
+ ## Advanced Template Patterns
369
+
370
+ ### Dynamic Role Assignment
371
+
372
+ ```ruby
373
+ markup = <<~POML
374
+ <poml>
375
+ <role>
376
+ <if condition="{{user_level}} == 'beginner'">Friendly Tutor</if>
377
+ <if condition="{{user_level}} == 'intermediate'">Technical Mentor</if>
378
+ <if condition="{{user_level}} == 'expert'">Peer Reviewer</if>
379
+ </role>
380
+
381
+ <task>{{task_description}}</task>
382
+
383
+ <if condition="{{user_level}} == 'beginner'">
384
+ <hint>Provide detailed explanations and examples</hint>
385
+ </if>
386
+ <if condition="{{user_level}} == 'expert'">
387
+ <hint>Focus on edge cases and performance considerations</hint>
388
+ </if>
389
+ </poml>
390
+ POML
391
+ ```
392
+
393
+ ### Template Composition
394
+
395
+ ```ruby
396
+ def create_review_prompt(review_type, language, complexity)
397
+ markup = <<~POML
398
+ <poml>
399
+ <meta variables='{"review_type": "#{review_type}", "language": "#{language}"}' />
400
+
401
+ <role>Senior {{language}} Developer</role>
402
+ <task>Perform {{review_type}} review</task>
403
+
404
+ <if condition="{{review_type}} == 'security'">
405
+ <p>Security Review Checklist:</p>
406
+ <list>
407
+ <item>Input validation and sanitization</item>
408
+ <item>Authentication and authorization</item>
409
+ <item>Data encryption and storage</item>
410
+ <item>Dependency vulnerabilities</item>
411
+ </list>
412
+ </if>
413
+
414
+ <if condition="{{review_type}} == 'performance'">
415
+ <p>Performance Review Checklist:</p>
416
+ <list>
417
+ <item>Algorithm complexity analysis</item>
418
+ <item>Database query optimization</item>
419
+ <item>Memory usage patterns</item>
420
+ <item>Caching strategies</item>
421
+ </list>
422
+ </if>
423
+
424
+ <if condition="{{review_type}} == 'code_quality'">
425
+ <p>Code Quality Review Checklist:</p>
426
+ <list>
427
+ <item>Code readability and maintainability</item>
428
+ <item>Design patterns and architecture</item>
429
+ <item>Test coverage and quality</item>
430
+ <item>Documentation completeness</item>
431
+ </list>
432
+ </if>
433
+ </poml>
434
+ POML
435
+
436
+ context = { 'complexity' => complexity }
437
+ Poml.process(markup: markup, context: context)
438
+ end
439
+
440
+ # Usage
441
+ security_prompt = create_review_prompt('security', 'Ruby', 'high')
442
+ performance_prompt = create_review_prompt('performance', 'Python', 'medium')
443
+ ```
444
+
445
+ ## Error Handling in Templates
446
+
447
+ ### Safe Variable Access
448
+
449
+ ```ruby
450
+ markup = <<~POML
451
+ <poml>
452
+ <role>Data Analyst</role>
453
+ <task>Generate report</task>
454
+
455
+ <if condition="{{report_data}}">
456
+ <p>Processing {{report_data.length}} records...</p>
457
+
458
+ <if condition="{{report_data.length}} > 1000">
459
+ <hint>Large dataset - consider sampling for initial analysis</hint>
460
+ </if>
461
+ </if>
462
+
463
+ <if condition="!{{report_data}}">
464
+ <p>⚠️ No data available for analysis</p>
465
+ </if>
466
+ </poml>
467
+ POML
468
+ ```
469
+
470
+ ### Default Values
471
+
472
+ ```ruby
473
+ def safe_template_processing(markup, context = {})
474
+ # Provide default values
475
+ defaults = {
476
+ 'environment' => 'development',
477
+ 'debug_mode' => true,
478
+ 'timeout' => 30
479
+ }
480
+
481
+ final_context = defaults.merge(context)
482
+ Poml.process(markup: markup, context: final_context)
483
+ end
484
+ ```
485
+
486
+ ## Performance Considerations
487
+
488
+ ### Template Caching
489
+
490
+ ```ruby
491
+ class TemplateProcessor
492
+ def initialize
493
+ @template_cache = {}
494
+ @result_cache = {}
495
+ end
496
+
497
+ def process_with_cache(template_key, markup, context)
498
+ # Cache compiled templates
499
+ @template_cache[template_key] ||= markup
500
+
501
+ # Cache results for identical context
502
+ cache_key = "#{template_key}:#{context.hash}"
503
+ @result_cache[cache_key] ||= Poml.process(
504
+ markup: @template_cache[template_key],
505
+ context: context
506
+ )
507
+ end
508
+ end
509
+ ```
510
+
511
+ ### Large Dataset Handling
512
+
513
+ ```ruby
514
+ markup = <<~POML
515
+ <poml>
516
+ <role>Data Processor</role>
517
+ <task>Process dataset</task>
518
+
519
+ <if condition="{{items.length}} > 100">
520
+ <p>Large dataset detected ({{items.length}} items)</p>
521
+ <hint>Consider batch processing or pagination</hint>
522
+ </if>
523
+
524
+ <p>Sample items:</p>
525
+ <list>
526
+ <for variable="item" items="{{items}}">
527
+ <if condition="{{item.index}} < 5">
528
+ <item>{{item.name}} - {{item.value}}</item>
529
+ </if>
530
+ </for>
531
+ </list>
532
+ </poml>
533
+ POML
534
+ ```
535
+
536
+ ## Next Steps
537
+
538
+ - Learn about [Output Formats](output-formats.md) for different use cases
539
+ - Explore [Schema Components](components/schema-components.md) for structured data
540
+ - Check [Tool Registration](advanced/tool-registration.md) for AI tool integration