poml 0.0.5 → 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.
- checksums.yaml +4 -4
- data/docs/tutorial/advanced/performance.md +695 -0
- data/docs/tutorial/advanced/tool-registration.md +776 -0
- data/docs/tutorial/basic-usage.md +351 -0
- data/docs/tutorial/components/chat-components.md +552 -0
- data/docs/tutorial/components/formatting.md +623 -0
- data/docs/tutorial/components/index.md +366 -0
- data/docs/tutorial/components/media-components.md +259 -0
- data/docs/tutorial/components/schema-components.md +668 -0
- data/docs/tutorial/index.md +184 -0
- data/docs/tutorial/output-formats.md +688 -0
- data/docs/tutorial/quickstart.md +30 -0
- data/docs/tutorial/template-engine.md +540 -0
- data/examples/303_new_component_syntax.poml +45 -0
- data/lib/poml/components/base.rb +150 -3
- data/lib/poml/components/content.rb +10 -3
- data/lib/poml/components/data.rb +539 -19
- data/lib/poml/components/examples.rb +235 -1
- data/lib/poml/components/formatting.rb +184 -18
- data/lib/poml/components/layout.rb +7 -2
- data/lib/poml/components/lists.rb +69 -35
- data/lib/poml/components/meta.rb +191 -6
- data/lib/poml/components/output_schema.rb +103 -0
- data/lib/poml/components/template.rb +72 -61
- data/lib/poml/components/text.rb +30 -1
- data/lib/poml/components/tool.rb +81 -0
- data/lib/poml/components/tool_definition.rb +427 -0
- data/lib/poml/components/tools.rb +14 -0
- data/lib/poml/components/utilities.rb +34 -18
- data/lib/poml/components.rb +29 -0
- data/lib/poml/context.rb +19 -4
- data/lib/poml/parser.rb +90 -64
- data/lib/poml/renderer.rb +191 -9
- data/lib/poml/template_engine.rb +138 -13
- data/lib/poml/version.rb +1 -1
- data/lib/poml.rb +16 -1
- data/readme.md +154 -27
- metadata +34 -4
- data/TUTORIAL.md +0 -987
@@ -0,0 +1,552 @@
|
|
1
|
+
# Chat Components
|
2
|
+
|
3
|
+
POML provides specialized components for creating structured AI conversations with proper role-based messaging.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
Chat components (`<ai>`, `<human>`, `<system>`) are designed to create structured conversation flows that work seamlessly across different AI platforms and output formats.
|
8
|
+
|
9
|
+
## System Component
|
10
|
+
|
11
|
+
The `<system>` component defines system-level instructions and context:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
require 'poml'
|
15
|
+
|
16
|
+
markup = <<~POML
|
17
|
+
<poml>
|
18
|
+
<system>
|
19
|
+
You are a helpful assistant specializing in Ruby programming.
|
20
|
+
Provide clear, practical solutions with code examples.
|
21
|
+
Always explain your reasoning and suggest best practices.
|
22
|
+
</system>
|
23
|
+
</poml>
|
24
|
+
POML
|
25
|
+
|
26
|
+
result = Poml.process(markup: markup, format: 'openai_chat')
|
27
|
+
puts JSON.pretty_generate(result)
|
28
|
+
```
|
29
|
+
|
30
|
+
Output:
|
31
|
+
|
32
|
+
```json
|
33
|
+
[
|
34
|
+
{
|
35
|
+
"role": "system",
|
36
|
+
"content": "You are a helpful assistant specializing in Ruby programming..."
|
37
|
+
}
|
38
|
+
]
|
39
|
+
```
|
40
|
+
|
41
|
+
## Human Component
|
42
|
+
|
43
|
+
The `<human>` component represents user messages and queries:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
markup = <<~POML
|
47
|
+
<poml>
|
48
|
+
<system>You are a code review assistant.</system>
|
49
|
+
|
50
|
+
<human>
|
51
|
+
Please review this Ruby method for potential improvements:
|
52
|
+
|
53
|
+
<code>
|
54
|
+
def calculate_total(items)
|
55
|
+
total = 0
|
56
|
+
items.each do |item|
|
57
|
+
total += item.price * item.quantity
|
58
|
+
end
|
59
|
+
total
|
60
|
+
end
|
61
|
+
</code>
|
62
|
+
</human>
|
63
|
+
</poml>
|
64
|
+
POML
|
65
|
+
|
66
|
+
result = Poml.process(markup: markup, format: 'openai_chat')
|
67
|
+
```
|
68
|
+
|
69
|
+
## AI Component
|
70
|
+
|
71
|
+
The `<ai>` component represents assistant responses and can be used for few-shot examples:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
markup = <<~POML
|
75
|
+
<poml>
|
76
|
+
<system>You are a Ruby expert providing code reviews.</system>
|
77
|
+
|
78
|
+
<human>How can I optimize this method?</human>
|
79
|
+
|
80
|
+
<ai>
|
81
|
+
Here's an optimized version using Ruby's built-in methods:
|
82
|
+
|
83
|
+
<code>
|
84
|
+
def calculate_total(items)
|
85
|
+
items.sum { |item| item.price * item.quantity }
|
86
|
+
end
|
87
|
+
</code>
|
88
|
+
|
89
|
+
This approach is more idiomatic and efficient.
|
90
|
+
</ai>
|
91
|
+
|
92
|
+
<human>Now please review this new code I've written:</human>
|
93
|
+
</poml>
|
94
|
+
POML
|
95
|
+
|
96
|
+
result = Poml.process(markup: markup, format: 'openai_chat')
|
97
|
+
```
|
98
|
+
|
99
|
+
## Multi-Turn Conversations
|
100
|
+
|
101
|
+
Create complex conversation flows with multiple exchanges:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
markup = <<~POML
|
105
|
+
<poml>
|
106
|
+
<system>
|
107
|
+
You are a technical interviewer conducting a Ruby programming interview.
|
108
|
+
Ask progressive questions to assess the candidate's knowledge.
|
109
|
+
</system>
|
110
|
+
|
111
|
+
<human>I'm ready for the Ruby interview questions.</human>
|
112
|
+
|
113
|
+
<ai>
|
114
|
+
Great! Let's start with a basic question:
|
115
|
+
|
116
|
+
What's the difference between a class method and an instance method in Ruby?
|
117
|
+
Can you provide examples of each?
|
118
|
+
</ai>
|
119
|
+
|
120
|
+
<human>
|
121
|
+
A class method is called on the class itself, while an instance method
|
122
|
+
is called on an instance of the class.
|
123
|
+
|
124
|
+
Class method: `User.find_by_email(email)`
|
125
|
+
Instance method: `user.save`
|
126
|
+
</human>
|
127
|
+
|
128
|
+
<ai>
|
129
|
+
Excellent! Now let's dive deeper. Can you explain how Ruby's method
|
130
|
+
lookup chain works? What happens when you call a method on an object?
|
131
|
+
</ai>
|
132
|
+
|
133
|
+
<human>{{candidate_response}}</human>
|
134
|
+
</poml>
|
135
|
+
POML
|
136
|
+
|
137
|
+
context = {
|
138
|
+
'candidate_response' => 'Please explain the method lookup process...'
|
139
|
+
}
|
140
|
+
|
141
|
+
result = Poml.process(markup: markup, context: context, format: 'openai_chat')
|
142
|
+
```
|
143
|
+
|
144
|
+
## Chat Components with Formatting
|
145
|
+
|
146
|
+
Chat components support nested formatting and structure:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
markup = <<~POML
|
150
|
+
<poml>
|
151
|
+
<system>You are a code documentation assistant.</system>
|
152
|
+
|
153
|
+
<human>
|
154
|
+
Please document this API endpoint:
|
155
|
+
|
156
|
+
<list>
|
157
|
+
<item><b>Method:</b> POST</item>
|
158
|
+
<item><b>Path:</b> /api/users</item>
|
159
|
+
<item><b>Purpose:</b> Create new user account</item>
|
160
|
+
</list>
|
161
|
+
</human>
|
162
|
+
|
163
|
+
<ai>
|
164
|
+
I'll create comprehensive documentation for this endpoint:
|
165
|
+
|
166
|
+
<h2>POST /api/users</h2>
|
167
|
+
|
168
|
+
<p><b>Description:</b> Creates a new user account in the system.</p>
|
169
|
+
|
170
|
+
<p><b>Request Body:</b></p>
|
171
|
+
<code>
|
172
|
+
{
|
173
|
+
"name": "string (required)",
|
174
|
+
"email": "string (required, unique)",
|
175
|
+
"password": "string (required, min 8 chars)"
|
176
|
+
}
|
177
|
+
</code>
|
178
|
+
|
179
|
+
<p><b>Response Codes:</b></p>
|
180
|
+
<list>
|
181
|
+
<item><code>201</code> - User created successfully</item>
|
182
|
+
<item><code>400</code> - Validation errors</item>
|
183
|
+
<item><code>409</code> - Email already exists</item>
|
184
|
+
</list>
|
185
|
+
</ai>
|
186
|
+
</poml>
|
187
|
+
POML
|
188
|
+
|
189
|
+
result = Poml.process(markup: markup, format: 'raw')
|
190
|
+
```
|
191
|
+
|
192
|
+
## Template Variables in Chat
|
193
|
+
|
194
|
+
Use template variables within chat components:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
markup = <<~POML
|
198
|
+
<poml>
|
199
|
+
<system>
|
200
|
+
You are a {{expertise_area}} expert helping with {{project_type}} projects.
|
201
|
+
Provide detailed, practical guidance based on industry best practices.
|
202
|
+
</system>
|
203
|
+
|
204
|
+
<human>
|
205
|
+
I'm working on a {{project_type}} and need help with {{specific_issue}}.
|
206
|
+
|
207
|
+
<p>Project Details:</p>
|
208
|
+
<list>
|
209
|
+
<item>Technology: {{technology_stack}}</item>
|
210
|
+
<item>Timeline: {{timeline}}</item>
|
211
|
+
<item>Team Size: {{team_size}}</item>
|
212
|
+
</list>
|
213
|
+
</human>
|
214
|
+
</poml>
|
215
|
+
POML
|
216
|
+
|
217
|
+
context = {
|
218
|
+
'expertise_area' => 'DevOps',
|
219
|
+
'project_type' => 'microservices deployment',
|
220
|
+
'specific_issue' => 'container orchestration',
|
221
|
+
'technology_stack' => 'Docker + Kubernetes',
|
222
|
+
'timeline' => '3 months',
|
223
|
+
'team_size' => '5 developers'
|
224
|
+
}
|
225
|
+
|
226
|
+
result = Poml.process(markup: markup, context: context, format: 'openai_chat')
|
227
|
+
```
|
228
|
+
|
229
|
+
## Conditional Chat Content
|
230
|
+
|
231
|
+
Use conditionals to create dynamic conversation flows:
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
markup = <<~POML
|
235
|
+
<poml>
|
236
|
+
<system>You are a debugging assistant.</system>
|
237
|
+
|
238
|
+
<human>I'm having an issue with my {{language}} code.</human>
|
239
|
+
|
240
|
+
<ai>
|
241
|
+
I'd be happy to help you debug your {{language}} code!
|
242
|
+
|
243
|
+
<if condition="{{language}} == 'Ruby'">
|
244
|
+
<p>For Ruby issues, I'll need to see:</p>
|
245
|
+
<list>
|
246
|
+
<item>The Ruby version you're using</item>
|
247
|
+
<item>Your Gemfile (if applicable)</item>
|
248
|
+
<item>The specific error message</item>
|
249
|
+
<item>The problematic code snippet</item>
|
250
|
+
</list>
|
251
|
+
</if>
|
252
|
+
|
253
|
+
<if condition="{{language}} == 'Python'">
|
254
|
+
<p>For Python issues, please provide:</p>
|
255
|
+
<list>
|
256
|
+
<item>Python version and virtual environment info</item>
|
257
|
+
<item>requirements.txt or pip freeze output</item>
|
258
|
+
<item>Full traceback of the error</item>
|
259
|
+
<item>Minimal code to reproduce the issue</item>
|
260
|
+
</list>
|
261
|
+
</if>
|
262
|
+
|
263
|
+
<p>Please share these details and I'll help you solve the problem.</p>
|
264
|
+
</ai>
|
265
|
+
</poml>
|
266
|
+
POML
|
267
|
+
|
268
|
+
context = { 'language' => 'Ruby' }
|
269
|
+
result = Poml.process(markup: markup, context: context, format: 'raw')
|
270
|
+
```
|
271
|
+
|
272
|
+
## Output Format Behavior
|
273
|
+
|
274
|
+
Chat components behave differently based on the output format:
|
275
|
+
|
276
|
+
### OpenAI Chat Format
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
markup = <<~POML
|
280
|
+
<poml>
|
281
|
+
<system>You are a helpful assistant.</system>
|
282
|
+
<human>What is Ruby?</human>
|
283
|
+
</poml>
|
284
|
+
POML
|
285
|
+
|
286
|
+
result = Poml.process(markup: markup, format: 'openai_chat')
|
287
|
+
# Returns: [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}]
|
288
|
+
```
|
289
|
+
|
290
|
+
### Raw Format
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
result = Poml.process(markup: markup, format: 'raw')
|
294
|
+
# Returns: Text with role boundaries like "===== system ====="
|
295
|
+
```
|
296
|
+
|
297
|
+
### LangChain Format
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
result = Poml.process(markup: markup, format: 'langchain')
|
301
|
+
# Returns: LangChain-compatible message structure
|
302
|
+
```
|
303
|
+
|
304
|
+
## Advanced Chat Patterns
|
305
|
+
|
306
|
+
### Interview Flow
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
markup = <<~POML
|
310
|
+
<poml>
|
311
|
+
<system>
|
312
|
+
You are conducting a technical interview for a {{position}} role.
|
313
|
+
Ask progressive questions starting from basic concepts to advanced topics.
|
314
|
+
Provide feedback and follow-up questions based on responses.
|
315
|
+
</system>
|
316
|
+
|
317
|
+
<human>I'm ready to begin the {{position}} interview.</human>
|
318
|
+
|
319
|
+
<ai>
|
320
|
+
Welcome to the {{position}} interview! Let's start with some foundational questions.
|
321
|
+
|
322
|
+
<p><b>Question 1:</b> {{first_question}}</p>
|
323
|
+
|
324
|
+
<p>Take your time to explain your thought process.</p>
|
325
|
+
</ai>
|
326
|
+
|
327
|
+
<human>{{candidate_answer_1}}</human>
|
328
|
+
|
329
|
+
<ai>
|
330
|
+
<if condition="{{question_difficulty}} == 'basic'">
|
331
|
+
Good start! Now let's move to something more challenging.
|
332
|
+
</if>
|
333
|
+
|
334
|
+
<if condition="{{question_difficulty}} == 'advanced'">
|
335
|
+
Excellent answer! You clearly understand the concepts well.
|
336
|
+
</if>
|
337
|
+
|
338
|
+
<p><b>Follow-up:</b> {{follow_up_question}}</p>
|
339
|
+
</ai>
|
340
|
+
</poml>
|
341
|
+
POML
|
342
|
+
```
|
343
|
+
|
344
|
+
### Debugging Session
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
markup = <<~POML
|
348
|
+
<poml>
|
349
|
+
<system>
|
350
|
+
You are a senior developer helping debug a complex issue.
|
351
|
+
Guide the user through systematic debugging steps.
|
352
|
+
</system>
|
353
|
+
|
354
|
+
<human>
|
355
|
+
I'm getting this error in production:
|
356
|
+
|
357
|
+
<code>{{error_message}}</code>
|
358
|
+
|
359
|
+
It happens intermittently and I can't reproduce it locally.
|
360
|
+
</human>
|
361
|
+
|
362
|
+
<ai>
|
363
|
+
Intermittent production-only errors can be tricky! Let's debug this systematically.
|
364
|
+
|
365
|
+
<p><b>First, let's gather information:</b></p>
|
366
|
+
<list>
|
367
|
+
<item>What's the frequency of this error?</item>
|
368
|
+
<item>Are there any patterns in timing or user actions?</item>
|
369
|
+
<item>What are the differences between your local and production environments?</item>
|
370
|
+
<item>Do you have logging around the error location?</item>
|
371
|
+
</list>
|
372
|
+
|
373
|
+
<p>Based on the error message, here are some initial hypotheses:</p>
|
374
|
+
|
375
|
+
<if condition="{{error_type}} == 'timeout'">
|
376
|
+
<list>
|
377
|
+
<item>Database connection pooling issues</item>
|
378
|
+
<item>External API timeouts</item>
|
379
|
+
<item>Load-related performance degradation</item>
|
380
|
+
</list>
|
381
|
+
</if>
|
382
|
+
|
383
|
+
<if condition="{{error_type}} == 'memory'">
|
384
|
+
<list>
|
385
|
+
<item>Memory leaks in long-running processes</item>
|
386
|
+
<item>Large dataset processing without pagination</item>
|
387
|
+
<item>Inefficient caching strategies</item>
|
388
|
+
</list>
|
389
|
+
</if>
|
390
|
+
</ai>
|
391
|
+
</poml>
|
392
|
+
POML
|
393
|
+
```
|
394
|
+
|
395
|
+
### Code Review Conversation
|
396
|
+
|
397
|
+
```ruby
|
398
|
+
markup = <<~POML
|
399
|
+
<poml>
|
400
|
+
<system>
|
401
|
+
You are a senior developer conducting a code review.
|
402
|
+
Provide constructive feedback focusing on maintainability, performance, and best practices.
|
403
|
+
</system>
|
404
|
+
|
405
|
+
<human>
|
406
|
+
Here's my implementation for the user authentication system:
|
407
|
+
|
408
|
+
<code>{{code_submission}}</code>
|
409
|
+
|
410
|
+
I'm particularly concerned about security and performance.
|
411
|
+
</human>
|
412
|
+
|
413
|
+
<ai>
|
414
|
+
Thanks for submitting this code! I'll review it focusing on security and performance as requested.
|
415
|
+
|
416
|
+
<p><b>Overall Assessment:</b> {{overall_assessment}}</p>
|
417
|
+
|
418
|
+
<p><b>Security Review:</b></p>
|
419
|
+
<list>
|
420
|
+
<for variable="security_issue" items="{{security_issues}}">
|
421
|
+
<item><b>{{security_issue.severity}}:</b> {{security_issue.description}}</item>
|
422
|
+
</for>
|
423
|
+
</list>
|
424
|
+
|
425
|
+
<p><b>Performance Considerations:</b></p>
|
426
|
+
<list>
|
427
|
+
<for variable="perf_issue" items="{{performance_issues}}">
|
428
|
+
<item>{{perf_issue.description}} - <i>{{perf_issue.solution}}</i></item>
|
429
|
+
</for>
|
430
|
+
</list>
|
431
|
+
|
432
|
+
<p><b>Recommended Changes:</b></p>
|
433
|
+
<code>{{suggested_improvements}}</code>
|
434
|
+
|
435
|
+
<p>Would you like me to explain any of these recommendations in more detail?</p>
|
436
|
+
</ai>
|
437
|
+
</poml>
|
438
|
+
POML
|
439
|
+
```
|
440
|
+
|
441
|
+
## Best Practices
|
442
|
+
|
443
|
+
### 1. Clear Role Definition
|
444
|
+
|
445
|
+
```ruby
|
446
|
+
# Good
|
447
|
+
<system>
|
448
|
+
You are a Ruby on Rails expert with 10+ years of experience.
|
449
|
+
Provide practical, production-ready solutions with security considerations.
|
450
|
+
</system>
|
451
|
+
|
452
|
+
# Better
|
453
|
+
<system>
|
454
|
+
You are a Senior Ruby on Rails Developer and Technical Lead specializing in:
|
455
|
+
- Performance optimization and scaling
|
456
|
+
- Security best practices and compliance
|
457
|
+
- Code architecture and maintainability
|
458
|
+
|
459
|
+
Always provide working code examples and explain trade-offs.
|
460
|
+
</system>
|
461
|
+
```
|
462
|
+
|
463
|
+
### 2. Structured Conversations
|
464
|
+
|
465
|
+
```ruby
|
466
|
+
# Structure conversations logically
|
467
|
+
<system>Context and role definition</system>
|
468
|
+
<human>Initial request or question</human>
|
469
|
+
<ai>Example response (for few-shot learning)</ai>
|
470
|
+
<human>Actual user input</human>
|
471
|
+
```
|
472
|
+
|
473
|
+
### 3. Use Formatting for Clarity
|
474
|
+
|
475
|
+
```ruby
|
476
|
+
<human>
|
477
|
+
<p>I need help with this problem:</p>
|
478
|
+
|
479
|
+
<p><b>Context:</b> {{context}}</p>
|
480
|
+
<p><b>Goal:</b> {{goal}}</p>
|
481
|
+
<p><b>Constraints:</b> {{constraints}}</p>
|
482
|
+
|
483
|
+
<p>Current code:</p>
|
484
|
+
<code>{{current_code}}</code>
|
485
|
+
</human>
|
486
|
+
```
|
487
|
+
|
488
|
+
### 4. Error Handling
|
489
|
+
|
490
|
+
```ruby
|
491
|
+
def safe_chat_processing(markup, context = {})
|
492
|
+
begin
|
493
|
+
result = Poml.process(markup: markup, context: context, format: 'openai_chat')
|
494
|
+
|
495
|
+
# Validate chat structure
|
496
|
+
if result.is_a?(Array) && result.all? { |msg| msg.is_a?(Hash) && msg['role'] && msg['content'] }
|
497
|
+
{ success: true, messages: result }
|
498
|
+
else
|
499
|
+
{ success: false, error: 'Invalid chat structure' }
|
500
|
+
end
|
501
|
+
rescue => e
|
502
|
+
{ success: false, error: e.message }
|
503
|
+
end
|
504
|
+
end
|
505
|
+
```
|
506
|
+
|
507
|
+
## Integration with AI Services
|
508
|
+
|
509
|
+
### OpenAI API
|
510
|
+
|
511
|
+
```ruby
|
512
|
+
require 'net/http'
|
513
|
+
require 'json'
|
514
|
+
|
515
|
+
def send_to_openai(poml_markup, context = {})
|
516
|
+
messages = Poml.process(
|
517
|
+
markup: poml_markup,
|
518
|
+
context: context,
|
519
|
+
format: 'openai_chat'
|
520
|
+
)
|
521
|
+
|
522
|
+
payload = {
|
523
|
+
model: 'gpt-4',
|
524
|
+
messages: messages,
|
525
|
+
max_tokens: 1000,
|
526
|
+
temperature: 0.7
|
527
|
+
}
|
528
|
+
|
529
|
+
# Send to OpenAI API...
|
530
|
+
end
|
531
|
+
```
|
532
|
+
|
533
|
+
### Claude API
|
534
|
+
|
535
|
+
```ruby
|
536
|
+
def send_to_claude(poml_markup, context = {})
|
537
|
+
# Convert to raw format for Claude
|
538
|
+
prompt = Poml.process(
|
539
|
+
markup: poml_markup,
|
540
|
+
context: context,
|
541
|
+
format: 'raw'
|
542
|
+
)
|
543
|
+
|
544
|
+
# Send to Claude API...
|
545
|
+
end
|
546
|
+
```
|
547
|
+
|
548
|
+
## Next Steps
|
549
|
+
|
550
|
+
- Learn about [Output Formats](../output-formats.md) for different AI services
|
551
|
+
- Explore [Schema Components](schema-components.md) for structured responses
|
552
|
+
- Check [Integration Examples](../integration/rails.md) for real-world usage
|