@riotprompt/riotprompt 0.0.2 → 0.0.4
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.
- package/.cursor/rules/focus-on-prompt.mdc +5 -0
- package/README.md +65 -492
- package/dist/builder.d.ts +3 -3
- package/dist/builder.js +9 -4
- package/dist/builder.js.map +1 -1
- package/dist/chat.js.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/formatter.js.map +1 -1
- package/dist/items/content.js.map +1 -1
- package/dist/items/context.js.map +1 -1
- package/dist/items/instruction.js.map +1 -1
- package/dist/items/parameters.js.map +1 -1
- package/dist/items/section.js.map +1 -1
- package/dist/items/trait.js.map +1 -1
- package/dist/items/weighted.js.map +1 -1
- package/dist/loader.js +1 -0
- package/dist/loader.js.map +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/override.d.ts +5 -5
- package/dist/override.js +47 -30
- package/dist/override.js.map +1 -1
- package/dist/parse/markdown.d.ts +1 -1
- package/dist/parse/markdown.js +3 -2
- package/dist/parse/markdown.js.map +1 -1
- package/dist/parse/text.js.map +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/parser.js +3 -3
- package/dist/parser.js.map +1 -1
- package/dist/prompt.js.map +1 -1
- package/dist/recipes.d.ts +373 -0
- package/dist/recipes.js +279 -0
- package/dist/recipes.js.map +1 -0
- package/dist/riotprompt.cjs +340 -40
- package/dist/riotprompt.cjs.map +1 -1
- package/dist/riotprompt.d.ts +3 -0
- package/dist/riotprompt.js +3 -0
- package/dist/riotprompt.js.map +1 -1
- package/dist/util/general.js.map +1 -1
- package/dist/util/markdown.js.map +1 -1
- package/dist/util/storage.js.map +1 -1
- package/dist/util/text.js.map +1 -1
- package/package.json +29 -24
- package/.gitcarve/config.yaml +0 -10
- package/.gitcarve/context/content.md +0 -11
- package/.markdown-doctest-setup.mjs +0 -23
- package/.nvmrc +0 -1
- package/docs/loader.md +0 -237
- package/docs/override.md +0 -323
- package/docs/parser.md +0 -130
- package/eslint.config.mjs +0 -82
- package/nodemon.json +0 -14
- package/vite.config.ts +0 -114
- package/vitest.config.ts +0 -25
package/README.md
CHANGED
|
@@ -1,513 +1,86 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
riotprompt helps you:
|
|
35
|
-
- Organize prompt elements into logical categories (instructions, content, context)
|
|
36
|
-
- Create reusable persona definitions with traits and instructions
|
|
37
|
-
- Group related items into sections
|
|
38
|
-
- Format everything consistently for different LLM models
|
|
39
|
-
|
|
40
|
-
## Installation
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
npm install @riotprompt
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Basic Usage
|
|
47
|
-
|
|
48
|
-
```js
|
|
49
|
-
import { createSection, createPrompt, Formatter, Section, Instruction } from '@riotprompt';
|
|
50
|
-
|
|
51
|
-
// Create a new prompt
|
|
52
|
-
const section: Section<Instruction> = createSection<Instruction>({ title: "Instructions" });
|
|
53
|
-
|
|
54
|
-
// Add instructions
|
|
55
|
-
section.add("Answer in a concise manner");
|
|
56
|
-
section.add("Provide code examples when appropriate");
|
|
57
|
-
|
|
58
|
-
// Verify parts of the output
|
|
59
|
-
console.log('Number of instructions:', section.items.length);
|
|
60
|
-
// Output: Number of instructions: 2
|
|
61
|
-
|
|
62
|
-
// Formatting a Section using Tags
|
|
63
|
-
const formatterTags = Formatter.create();
|
|
64
|
-
const formattedTags = formatterTags.format(section);
|
|
65
|
-
console.log(formattedTags);
|
|
66
|
-
// Output: <Instructions>
|
|
67
|
-
// Answer in a concise manner
|
|
68
|
-
//
|
|
69
|
-
// Provide code examples when appropriate
|
|
70
|
-
// </Instructions>
|
|
71
|
-
|
|
72
|
-
// Formatting a Section using Markdown
|
|
73
|
-
const formatterMarkdown = Formatter.create({ formatOptions: { sectionSeparator: "markdown" }});
|
|
74
|
-
const formattedMarkdown = formatterMarkdown.format(section)
|
|
75
|
-
console.log(formattedMarkdown);
|
|
76
|
-
// Output: # Instructions
|
|
77
|
-
//
|
|
78
|
-
// Answer in a concise manner
|
|
79
|
-
//
|
|
80
|
-
// Provide code examples when appropriate
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Core Concepts
|
|
86
|
-
|
|
87
|
-
riotprompt is built around several key concepts:
|
|
88
|
-
|
|
89
|
-
### WeightedText
|
|
90
|
-
|
|
91
|
-
The base type for all prompt elements. Each element has:
|
|
92
|
-
- `text`: The actual content
|
|
93
|
-
- `weight`: Optional weight value (for potential future ranking/prioritization)
|
|
94
|
-
|
|
95
|
-
### Prompt Structure Elements
|
|
96
|
-
|
|
97
|
-
riotprompt organizes prompts into four main categories:
|
|
98
|
-
|
|
99
|
-
1. **Personas**: Define who the LLM should be
|
|
100
|
-
- `name`: The persona's identifier
|
|
101
|
-
- `traits`: Characteristics the persona should embody (e.g., "You are a developer working on a project who needs to create a commit message")
|
|
102
|
-
- `instructions`: Specific guidance for the persona
|
|
103
|
-
|
|
104
|
-
2. **Instructions**: Tell the LLM how to respond
|
|
105
|
-
- General guidelines for response format, tone, etc.
|
|
106
|
-
|
|
107
|
-
3. **Content**: What the LLM should respond to
|
|
108
|
-
- The actual query or task
|
|
109
|
-
|
|
110
|
-
4. **Context**: Provide background information
|
|
111
|
-
- Additional context that helps the LLM understand the request
|
|
112
|
-
|
|
113
|
-
### Sections
|
|
114
|
-
|
|
115
|
-
Groups related items together:
|
|
116
|
-
- `title`: Section name
|
|
117
|
-
- `items`: Collection of related elements
|
|
118
|
-
|
|
119
|
-
## Advanced Usage
|
|
120
|
-
|
|
121
|
-
### Creating Sections
|
|
122
|
-
|
|
123
|
-
```js
|
|
124
|
-
import { createSection, Formatter, Section, Instruction, Context } from '@riotprompt';
|
|
125
|
-
|
|
126
|
-
// Create a section for coding best practices
|
|
127
|
-
const instructions: Section<Instruction> = createSection<Instruction>({ title: "Instructions" });
|
|
128
|
-
instructions.add("Follow DRY (Don't Repeat Yourself) principles");
|
|
129
|
-
instructions.add("Write readable code with clear variable names");
|
|
130
|
-
instructions.add("Add comments for complex logic");
|
|
131
|
-
|
|
132
|
-
const writerPersona: Section<Instruction> = createSection<Instruction>({ title: "Writer Persona" });
|
|
133
|
-
writerPersona.add("You are an amazingly talented writer who is awesome.");
|
|
134
|
-
|
|
135
|
-
const literatureContext: Section<Context> = createSection<Context>({ title: "Literature Context" });
|
|
136
|
-
literatureContext.add("Here is the full text of a really long book.");
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### Setting Section and Item Weights
|
|
140
|
-
|
|
141
|
-
riotprompt allows you to assign weights to sections and individual items within those sections. This can be useful for future enhancements where prompt elements might be prioritized or selected based on their weight.
|
|
142
|
-
|
|
143
|
-
You can define `weight` for the section itself and a default `itemWeight` for items added to that section using `SectionOptions`. Additionally, `parameters` can be defined at the section level and will be passed down to items added to that section.
|
|
144
|
-
|
|
145
|
-
```js
|
|
146
|
-
import { createSection, Formatter, Section, Instruction } from '@riotprompt';
|
|
147
|
-
|
|
148
|
-
// Create a section with specific weights and parameters
|
|
149
|
-
const weightedSection: Section<Instruction> = createSection<Instruction>({
|
|
150
|
-
title: "Weighted Topics",
|
|
151
|
-
weight: 10, // Weight for the entire section
|
|
152
|
-
itemWeight: 5, // Default weight for items in this section
|
|
153
|
-
parameters: { topic: "advanced" } // Parameters passed to items
|
|
1
|
+
# 🔥 RiotPrompt
|
|
2
|
+
|
|
3
|
+
A powerful, flexible prompt building library for AI applications with zero hardcoded assumptions.
|
|
4
|
+
|
|
5
|
+
## 🎯 Features
|
|
6
|
+
|
|
7
|
+
- **Generic & Extensible**: No hardcoded domain concepts - build any type of prompt
|
|
8
|
+
- **Template System**: Create reusable templates for common patterns
|
|
9
|
+
- **Declarative Configuration**: Simple object-based prompt creation
|
|
10
|
+
- **Type-Safe**: Full TypeScript support with excellent IntelliSense
|
|
11
|
+
- **Override System**: Customize prompts with hierarchical overrides
|
|
12
|
+
- **Multiple Content Types**: Support for files, directories, and inline content
|
|
13
|
+
|
|
14
|
+
## 🚀 Quick Start
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { cook, registerTemplates } from 'riotprompt';
|
|
18
|
+
|
|
19
|
+
// Simple prompt creation
|
|
20
|
+
const prompt = await cook({
|
|
21
|
+
basePath: __dirname,
|
|
22
|
+
persona: { content: 'You are a helpful AI assistant' },
|
|
23
|
+
instructions: [
|
|
24
|
+
{ content: 'Analyze the provided content carefully' },
|
|
25
|
+
{ path: 'instructions/guidelines.md' },
|
|
26
|
+
],
|
|
27
|
+
content: [
|
|
28
|
+
{ content: sourceData, title: 'Source Data', weight: 1.0 },
|
|
29
|
+
{ directories: ['examples/'], weight: 0.5 },
|
|
30
|
+
],
|
|
31
|
+
context: [
|
|
32
|
+
{ content: 'Additional context', title: 'Context' },
|
|
33
|
+
],
|
|
154
34
|
});
|
|
155
35
|
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
### Using Parameters for Customization
|
|
163
|
-
|
|
164
|
-
riotprompt supports dynamic content in your prompts through the use of parameters. Parameters allow you to define placeholders in your prompt text (e.g., `{{variable}}`) and replace them with specific values when the prompt is created or formatted. This is a simple yet powerful way to customize prompts for different scenarios without altering the core structure.
|
|
165
|
-
|
|
166
|
-
Parameters can be passed when creating a prompt, a persona, or a section. They can also be supplied directly when adding individual items like instructions, content, or context if those items are strings with placeholders.
|
|
167
|
-
|
|
168
|
-
```js
|
|
169
|
-
import { createSection, createParameters, Formatter, Section, Instruction, Parameters } from '@riotprompt';
|
|
170
|
-
|
|
171
|
-
const parameters: Parameters = createParameters({
|
|
172
|
-
"targetLanguage": "Spanish",
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
const instructions: Section<Instruction> = createSection({ title: "Instructions", parameters });
|
|
176
|
-
instructions.add("Translate the following text to {{targetLanguage}}.");
|
|
177
|
-
|
|
178
|
-
const formatter = Formatter.create({ formatOptions: { sectionSeparator: "markdown" }});
|
|
179
|
-
const formatted = formatter.format(instructions);
|
|
180
|
-
console.log(formatted);
|
|
181
|
-
// Output: # Instructions
|
|
182
|
-
// Translate the following text to Spanish
|
|
183
|
-
//
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Parsing Markdown for Section Creation
|
|
187
|
-
|
|
188
|
-
riotprompt can simplify the process of structuring your prompts by parsing Markdown content. When you provide Markdown text, riotprompt can automatically convert Markdown headers (e.g., `# Title`, `## Subtitle`) into `Section` objects. The text of the header becomes the title of the `Section`.
|
|
189
|
-
|
|
190
|
-
This allows you to draft complex prompt structures in a familiar Markdown format and then easily import them into riotprompt. For instance, a document like this:
|
|
191
|
-
|
|
192
|
-
```markdown
|
|
193
|
-
# Main Topic
|
|
194
|
-
Some general instructions or content.
|
|
195
|
-
|
|
196
|
-
## Sub-Topic 1
|
|
197
|
-
Details about the first sub-topic.
|
|
198
|
-
|
|
199
|
-
### Sub-Sub-Topic A
|
|
200
|
-
Further details.
|
|
201
|
-
|
|
202
|
-
## Sub-Topic 2
|
|
203
|
-
Details about the second sub-topic.
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Could be parsed into a main section titled "Main Topic" containing text and two sub-sections: "Sub-Topic 1" (which itself contains a nested section "Sub-Sub-Topic A") and "Sub-Topic 2". The content under each header would become items within the respective sections.
|
|
207
|
-
|
|
208
|
-
```js
|
|
209
|
-
import { Parser, Formatter } from '@riotprompt';
|
|
210
|
-
|
|
211
|
-
// Markdown content with sections
|
|
212
|
-
const markdownContent = `
|
|
213
|
-
# Instructions
|
|
214
|
-
Follow these guidelines when writing code.
|
|
215
|
-
|
|
216
|
-
## Best Practices
|
|
217
|
-
- Keep functions small and focused
|
|
218
|
-
- Use meaningful variable names
|
|
219
|
-
|
|
220
|
-
## Documentation
|
|
221
|
-
- Comment complex logic
|
|
222
|
-
- Document public APIs thoroughly
|
|
223
|
-
`;
|
|
224
|
-
|
|
225
|
-
// Parse the Markdown into a Section structure
|
|
226
|
-
const parser = Parser.create();
|
|
227
|
-
|
|
228
|
-
const parsedSection = parser.parse(markdownContent);
|
|
229
|
-
|
|
230
|
-
// Now you can manipulate the parsed sections
|
|
231
|
-
const bestPracticesSection = parsedSection.items[1]; // Accessing the "Best Practices" section
|
|
232
|
-
bestPracticesSection.add("- Write tests for your code");
|
|
233
|
-
|
|
234
|
-
// Format the resulting section structure
|
|
235
|
-
const formatter = Formatter.create();
|
|
236
|
-
const formattedPrompt = formatter.format(parsedSection);
|
|
237
|
-
console.log(formattedPrompt);
|
|
238
|
-
/* Output:
|
|
239
|
-
<Instructions>
|
|
240
|
-
Follow these guidelines when writing code.
|
|
241
|
-
|
|
242
|
-
<section title="Best Practices">
|
|
243
|
-
- Keep functions small and focused
|
|
244
|
-
- Use meaningful variable names
|
|
245
|
-
- Write tests for your code
|
|
246
|
-
</section>
|
|
247
|
-
|
|
248
|
-
<section title="Documentation">
|
|
249
|
-
- Comment complex logic
|
|
250
|
-
- Document public APIs thoroughly
|
|
251
|
-
</section>
|
|
252
|
-
</Instructions>
|
|
253
|
-
*/
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
For more information, see the [riotprompt Parser Documentation](docs/parser.md)
|
|
257
|
-
|
|
258
|
-
### Overriding Prompt Content
|
|
259
|
-
|
|
260
|
-
riotprompt's Override utility allows you to customize or replace parts of a prompt without altering the original prompt files. This is particularly useful in larger applications where you have default prompt templates but want to adjust certain sections for specific use cases, users, or environments. By using overrides, you can maintain a clean separation between core prompt content and custom modifications.
|
|
261
|
-
|
|
262
|
-
The override system works by looking for specially-named files in an override directory that correspond to your prompt files. You can completely override a section (replace it entirely), prepend content (insert before the original), or append content (insert after the original). This is all done through a simple file naming convention where files with the same name fully override, files ending in `-pre.md` prepend content, and files ending in `-post.md` append content.
|
|
263
|
-
|
|
264
|
-
For more information, see the [riotprompt Override Documentation](docs/override.md)
|
|
265
|
-
|
|
266
|
-
### Building Prompts
|
|
267
|
-
|
|
268
|
-
The riotprompt library provides a powerful Builder pattern for constructing complex prompts programmatically. The Builder allows you to assemble prompts from various sources including files, directories, and inline content.
|
|
269
|
-
|
|
270
|
-
#### Using the Builder
|
|
271
|
-
|
|
272
|
-
The Builder provides a fluent interface for assembling prompts from various sources:
|
|
273
|
-
|
|
274
|
-
<!-- skip-example -->
|
|
275
|
-
```js
|
|
276
|
-
import { Builder } from '@riotprompt';
|
|
277
|
-
|
|
278
|
-
// Create a builder instance
|
|
279
|
-
const builder = Builder.create({
|
|
280
|
-
basePath: './prompts', // Base directory for prompt files
|
|
281
|
-
overridePath: './overrides', // Optional directory for override files
|
|
282
|
-
overrides: true, // Whether to apply overrides
|
|
283
|
-
parameters: { role: 'expert' } // Optional parameters for substitution
|
|
36
|
+
// Register and use templates
|
|
37
|
+
registerTemplates({
|
|
38
|
+
'analysis': {
|
|
39
|
+
persona: { content: 'You are an expert analyst' },
|
|
40
|
+
instructions: [{ content: 'Provide detailed analysis' }],
|
|
41
|
+
},
|
|
284
42
|
});
|
|
285
43
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
.loadContext(['./context/people', './context/projects'])
|
|
291
|
-
.addContent('Here is some code I want you to look at.')
|
|
292
|
-
.build();
|
|
293
|
-
|
|
294
|
-
// Format and use the prompt with your LLM API
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
#### Builder Methods
|
|
298
|
-
|
|
299
|
-
The Builder supports the following methods:
|
|
300
|
-
|
|
301
|
-
- **`addPersonaPath(path)`**: Load a persona from a file
|
|
302
|
-
- **`addContextPath(path)`**: Load context from a file
|
|
303
|
-
- **`addInstructionPath(path)`**: Load instructions from a file
|
|
304
|
-
- **`addContentPath(path)`**: Load content from a file
|
|
305
|
-
- **`addContent(text)`**: Add content directly as a string
|
|
306
|
-
- **`addContext(text)`**: Add context directly as a string
|
|
307
|
-
- **`loadContext(directories)`**: Load context from multiple directories
|
|
308
|
-
- **`loadContent(directories)`**: Load content from multiple directories
|
|
309
|
-
- **`build()`**: Assemble the final prompt
|
|
310
|
-
|
|
311
|
-
All methods return the builder instance for chaining, and the `build()` method returns a Promise that resolves to a `Prompt` object.
|
|
312
|
-
|
|
313
|
-
#### Loading from Directories
|
|
314
|
-
|
|
315
|
-
The Builder can load content from entire directories:
|
|
316
|
-
|
|
317
|
-
<!-- skip-example -->
|
|
318
|
-
```js
|
|
319
|
-
import { Builder } from '@riotprompt/builder';
|
|
320
|
-
|
|
321
|
-
const builder = Builder.create({
|
|
322
|
-
basePath: './prompts',
|
|
44
|
+
const analysisPrompt = await cook({
|
|
45
|
+
basePath: __dirname,
|
|
46
|
+
template: 'analysis',
|
|
47
|
+
content: [{ content: dataToAnalyze, title: 'Data' }],
|
|
323
48
|
});
|
|
324
|
-
|
|
325
|
-
// Load all files from specific directories
|
|
326
|
-
const prompt = await builder
|
|
327
|
-
.loadContext(['context/user', 'context/project'])
|
|
328
|
-
.loadContent(['content/queries'])
|
|
329
|
-
.build();
|
|
330
49
|
```
|
|
331
50
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
Once you have a `Section` object, whether created directly, through Markdown parsing, or as part of a `riotprompt` instance (e.g., `prompt.instructionsSection`), you have several methods to manage its contents. These methods allow for dynamic construction and modification of your prompt structure.
|
|
335
|
-
|
|
336
|
-
The `Section` interface provides the following methods for item manipulation:
|
|
337
|
-
|
|
338
|
-
- **`add(item: T | Section<T> | string, options?: WeightedOptions): Section<T>`**
|
|
339
|
-
Appends a new item or a nested section to the end of the section's item list. If a string is provided, it's typically converted into an appropriate `WeightedText` object (e.g., `Instruction`, `ContentText`).
|
|
340
|
-
```typescript
|
|
341
|
-
mySection.add("New item at the end");
|
|
342
|
-
const nestedSection = createSection("Nested");
|
|
343
|
-
mySection.add(nestedSection);
|
|
344
|
-
```
|
|
51
|
+
## 📚 Documentation
|
|
345
52
|
|
|
346
|
-
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
```
|
|
53
|
+
- [Core Concepts](docs/public/core-concepts.md)
|
|
54
|
+
- [Recipes System](docs/public/recipes.md)
|
|
55
|
+
- [API Reference](docs/public/api-reference.md)
|
|
56
|
+
- [Template Configuration](docs/public/template-configuration.md)
|
|
351
57
|
|
|
352
|
-
|
|
353
|
-
Adds a new item or a nested section to the beginning of the section's item list.
|
|
354
|
-
```typescript
|
|
355
|
-
mySection.prepend("Item at the very beginning");
|
|
356
|
-
```
|
|
58
|
+
## 🔧 Installation
|
|
357
59
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
mySection.insert(1, "Item at index 1"); // Inserts after the first item
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
- **`replace(index: number, item: T | Section<T> | string, options?: WeightedOptions): Section<T>`**
|
|
365
|
-
Replaces the item at the specified `index` with a new item or nested section.
|
|
366
|
-
```typescript
|
|
367
|
-
mySection.replace(0, "Replaced first item");
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
- **`remove(index: number): Section<T>`**
|
|
371
|
-
Removes the item at the specified `index` from the item list.
|
|
372
|
-
```typescript
|
|
373
|
-
mySection.remove(0); // Removes the first item
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
These methods return the `Section` instance itself, allowing for fluent chaining of operations:
|
|
377
|
-
|
|
378
|
-
```js
|
|
379
|
-
import { createSection, Formatter, Section, Instruction } from '@riotprompt';
|
|
380
|
-
|
|
381
|
-
const mySection: Section<Instruction> = createSection({ title: "Example" });
|
|
382
|
-
|
|
383
|
-
mySection
|
|
384
|
-
.add("First item")
|
|
385
|
-
.prepend("Actually, this is first")
|
|
386
|
-
.insert(1, "This goes second")
|
|
387
|
-
.remove(2); // Removes "First item"
|
|
388
|
-
|
|
389
|
-
const formatter = Formatter.create({ formatOptions: { sectionSeparator: "markdown" }})
|
|
390
|
-
const formatted = formatter.format( mySection );
|
|
391
|
-
console.log( formatted );
|
|
392
|
-
// Output: # Example
|
|
393
|
-
//
|
|
394
|
-
// Actually, this is first
|
|
395
|
-
//
|
|
396
|
-
// This goes second
|
|
397
|
-
```
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
### Using the riotprompt Loader for File-Based Prompts
|
|
401
|
-
|
|
402
|
-
riotprompt provides a Loader utility that allows you to load prompt templates from external files. This is particularly useful when you want to:
|
|
403
|
-
|
|
404
|
-
- Store complex prompts as separate files
|
|
405
|
-
- Share prompt templates across different parts of your application
|
|
406
|
-
- Keep your prompt content separate from your application code
|
|
407
|
-
|
|
408
|
-
The Loader supports various file formats and can automatically parse the content into the appropriate Section structures.
|
|
409
|
-
|
|
410
|
-
The Loader works seamlessly with the Parser to convert structured content into riotprompt's internal representation, allowing you to focus on writing clear prompts rather than managing their implementation details.
|
|
411
|
-
|
|
412
|
-
For more documentation on the Loader, see the [riotprompt Loader Documentation](docs/loader.md)
|
|
413
|
-
|
|
414
|
-
### Customizing Format Options
|
|
415
|
-
|
|
416
|
-
riotprompt supports various formatting styles to organize your prompt elements:
|
|
417
|
-
|
|
418
|
-
#### Available Formatting Options
|
|
419
|
-
|
|
420
|
-
- **areaSeparator**: Determines how major areas (Instructions, Content, Context) are formatted
|
|
421
|
-
- `"tag"`: Uses XML-style tags `<instructions>...</instructions>`
|
|
422
|
-
- `"markdown"`: Uses markdown headers `#### Instructions`
|
|
423
|
-
|
|
424
|
-
- **sectionSeparator**: Determines how sections within areas are formatted
|
|
425
|
-
- `"tag"`: Uses XML-style tags `<section title="Best Practices">...</section>`
|
|
426
|
-
- `"markdown"`: Uses markdown subheaders `#### Section : Best Practices`
|
|
427
|
-
|
|
428
|
-
#### Examples of Different Separator Styles
|
|
429
|
-
|
|
430
|
-
Here's how the same prompt would be formatted using different separator styles:
|
|
431
|
-
|
|
432
|
-
**Tag Style (Default)**
|
|
433
|
-
|
|
434
|
-
```
|
|
435
|
-
<instructions>
|
|
436
|
-
Answer in a concise manner
|
|
437
|
-
Provide code examples when appropriate
|
|
438
|
-
|
|
439
|
-
<section title="Best Practices">
|
|
440
|
-
Follow DRY (Don't Repeat Yourself) principles
|
|
441
|
-
Write readable code with clear variable names
|
|
442
|
-
Add comments for complex logic
|
|
443
|
-
</section>
|
|
444
|
-
</instructions>
|
|
445
|
-
|
|
446
|
-
<contents>
|
|
447
|
-
Explain how promises work in JavaScript
|
|
448
|
-
</contents>
|
|
449
|
-
|
|
450
|
-
<context>
|
|
451
|
-
This is for a beginner JavaScript tutorial
|
|
452
|
-
</context>
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
**Markdown Style**
|
|
456
|
-
|
|
457
|
-
```
|
|
458
|
-
#### Instructions
|
|
459
|
-
|
|
460
|
-
Answer in a concise manner
|
|
461
|
-
Provide code examples when appropriate
|
|
462
|
-
|
|
463
|
-
#### Section : Best Practices
|
|
464
|
-
|
|
465
|
-
Follow DRY (Don't Repeat Yourself) principles
|
|
466
|
-
Write readable code with clear variable names
|
|
467
|
-
Add comments for complex logic
|
|
468
|
-
|
|
469
|
-
#### Contents
|
|
470
|
-
|
|
471
|
-
Explain how promises work in JavaScript
|
|
472
|
-
|
|
473
|
-
#### Context
|
|
474
|
-
|
|
475
|
-
This is for a beginner JavaScript tutorial
|
|
60
|
+
```bash
|
|
61
|
+
npm install riotprompt
|
|
476
62
|
```
|
|
477
63
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
- **Anthropic (Claude)** generally recommends using XML-style tags to clearly delineate sections of prompts
|
|
481
|
-
- **OpenAI (GPT)** models work well with both markdown-style formatting and XML tags
|
|
482
|
-
|
|
483
|
-
The field of prompt engineering is rapidly evolving, with new research and best practices emerging regularly. riotprompt's flexible formatting system allows you to adapt to these changes without rewriting your prompts entirely.
|
|
484
|
-
|
|
485
|
-
By separating the structure of your prompt (instructions, context, content) from its formatting, riotprompt makes it easier to experiment with different formatting approaches to find what works best for your specific use case and model.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
## Model Support
|
|
64
|
+
## 💡 Philosophy
|
|
489
65
|
|
|
490
|
-
|
|
491
|
-
- gpt-4o
|
|
492
|
-
- gpt-4o-mini
|
|
493
|
-
- o1-mini
|
|
494
|
-
- o1
|
|
495
|
-
- o1-preview
|
|
496
|
-
- o1-pro
|
|
497
|
-
- o3-mini
|
|
66
|
+
RiotPrompt is designed to be completely generic and unopinionated. Unlike other prompt libraries that assume specific use cases, RiotPrompt provides the building blocks for any prompt-based application while maintaining type safety and developer experience.
|
|
498
67
|
|
|
499
|
-
|
|
68
|
+
## 🏗️ Architecture
|
|
500
69
|
|
|
501
|
-
|
|
70
|
+
- **Cook Function**: Core prompt creation engine
|
|
71
|
+
- **Template System**: Reusable configuration patterns
|
|
72
|
+
- **Content Processing**: Flexible content handling (files, directories, inline)
|
|
73
|
+
- **Override System**: Hierarchical customization
|
|
74
|
+
- **Type Safety**: Full TypeScript support throughout
|
|
502
75
|
|
|
503
|
-
##
|
|
76
|
+
## 🤝 Contributing
|
|
504
77
|
|
|
505
|
-
|
|
78
|
+
Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
506
79
|
|
|
507
|
-
##
|
|
80
|
+
## 📄 License
|
|
508
81
|
|
|
509
|
-
|
|
82
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
510
83
|
|
|
511
|
-
|
|
84
|
+
---
|
|
512
85
|
|
|
513
|
-
|
|
86
|
+
*Build better prompts, faster.*
|
package/dist/builder.d.ts
CHANGED
|
@@ -4,21 +4,21 @@ import { Prompt } from './riotprompt';
|
|
|
4
4
|
declare const OptionSchema: z.ZodObject<{
|
|
5
5
|
logger: z.ZodDefault<z.ZodOptional<z.ZodAny>>;
|
|
6
6
|
basePath: z.ZodString;
|
|
7
|
-
|
|
7
|
+
overridePaths: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
8
8
|
overrides: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
9
9
|
parameters: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>, "many">]>>>>;
|
|
10
10
|
}, "strip", z.ZodTypeAny, {
|
|
11
11
|
parameters: Record<string, string | number | boolean | (string | number | boolean)[]>;
|
|
12
12
|
overrides: boolean;
|
|
13
13
|
basePath: string;
|
|
14
|
-
|
|
14
|
+
overridePaths: string[];
|
|
15
15
|
logger?: any;
|
|
16
16
|
}, {
|
|
17
17
|
basePath: string;
|
|
18
18
|
parameters?: Record<string, string | number | boolean | (string | number | boolean)[]> | undefined;
|
|
19
19
|
logger?: any;
|
|
20
20
|
overrides?: boolean | undefined;
|
|
21
|
-
|
|
21
|
+
overridePaths?: string[] | undefined;
|
|
22
22
|
}>;
|
|
23
23
|
export type Options = z.infer<typeof OptionSchema>;
|
|
24
24
|
export type OptionsParam = Required<Pick<Options, 'basePath'>> & Partial<Omit<Options, 'basePath'>>;
|
package/dist/builder.js
CHANGED
|
@@ -9,11 +9,14 @@ import './formatter.js';
|
|
|
9
9
|
import { create as create$1 } from './parser.js';
|
|
10
10
|
import { create as create$3 } from './loader.js';
|
|
11
11
|
import { create as create$2 } from './override.js';
|
|
12
|
+
import './recipes.js';
|
|
12
13
|
|
|
13
14
|
const OptionSchema = z.object({
|
|
14
15
|
logger: z.any().optional().default(DEFAULT_LOGGER),
|
|
15
16
|
basePath: z.string(),
|
|
16
|
-
|
|
17
|
+
overridePaths: z.array(z.string()).optional().default([
|
|
18
|
+
"./"
|
|
19
|
+
]),
|
|
17
20
|
overrides: z.boolean().optional().default(false),
|
|
18
21
|
parameters: ParametersSchema.optional().default({})
|
|
19
22
|
});
|
|
@@ -25,7 +28,9 @@ const create = (builderOptions)=>{
|
|
|
25
28
|
});
|
|
26
29
|
const override$1 = create$2({
|
|
27
30
|
logger,
|
|
28
|
-
|
|
31
|
+
configDirs: options.overridePaths || [
|
|
32
|
+
"./"
|
|
33
|
+
],
|
|
29
34
|
overrides: options.overrides || false
|
|
30
35
|
});
|
|
31
36
|
const loader$1 = create$3({
|
|
@@ -117,7 +122,7 @@ const create = (builderOptions)=>{
|
|
|
117
122
|
const addContent = async (content, sectionOptions = {})=>{
|
|
118
123
|
logger.debug("Adding content", typeof content);
|
|
119
124
|
const currentOptions = loadOptions(sectionOptions);
|
|
120
|
-
const parsedContentSection = parser$1.parse(content, currentOptions);
|
|
125
|
+
const parsedContentSection = await parser$1.parse(content, currentOptions);
|
|
121
126
|
contentSection.add(parsedContentSection);
|
|
122
127
|
return instance;
|
|
123
128
|
};
|
|
@@ -125,7 +130,7 @@ const create = (builderOptions)=>{
|
|
|
125
130
|
const addContext = async (context, sectionOptions = {})=>{
|
|
126
131
|
logger.debug("Adding context", typeof context);
|
|
127
132
|
const currentOptions = loadOptions(sectionOptions);
|
|
128
|
-
const parsedContextSection = parser$1.parse(context, currentOptions);
|
|
133
|
+
const parsedContextSection = await parser$1.parse(context, currentOptions);
|
|
129
134
|
contextSection.add(parsedContextSection);
|
|
130
135
|
return instance;
|
|
131
136
|
};
|