@riotprompt/riotprompt 0.0.13 → 0.0.15

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.
@@ -5,47 +5,58 @@
5
5
  ## Core Concepts
6
6
 
7
7
  ### Prompt Structure
8
- A `Prompt` in RiotPrompt is not a string; it is a structured object containing four main components:
8
+ A `Prompt` in RiotPrompt is not a string; it is a structured object containing multiple components that map to different aspects of prompt engineering:
9
9
 
10
10
  1. **Persona**: Defines *who* the AI is (System Prompt).
11
11
  2. **Instructions**: Defines *what* the AI should do (User Prompt / Task).
12
12
  3. **Context**: Background information, data, or documents needed to perform the task.
13
- 4. **Content**: Specific input data to be processed in this execution (optional, often merged with Context in simpler use cases).
13
+ 4. **Content**: Specific input data to be processed in this execution.
14
+ 5. **Constraints**: Operational boundaries (e.g., word count, format restrictions).
15
+ 6. **Tone**: Style guidelines (e.g., professional, humorous).
16
+ 7. **Examples**: Few-shot examples to demonstrate desired behavior.
17
+ 8. **Reasoning**: Instructions on the thinking process (e.g., Chain of Thought).
18
+ 9. **ResponseFormat**: Instructions on the output structure.
19
+ 10. **Recap**: Final reminders or summaries.
20
+ 11. **Safeguards**: Safety guidelines.
14
21
 
15
22
  ### Section System
16
23
  The fundamental building block is the `Section<T>`.
17
24
  * A `Section` contains a list of items (of type `T`) and can also contain nested `Sections`.
18
- * This allows for recursive, hierarchical structures (e.g., a Context section containing a "Market Data" section, which contains a "Q1 Results" section).
19
- * **Weighted Items**: Most items extend `Weighted`, allowing them to have associated weights or parameters for advanced optimization (though simple usage ignores this).
25
+ * This allows for recursive, hierarchical structures.
26
+ * **Weighted Items**: Most items extend `Weighted`, allowing them to have associated weights or parameters for advanced optimization.
20
27
 
21
28
  ## Module Structure
22
29
 
23
30
  The project is organized into distinct logical modules:
24
31
 
25
32
  * **`src/riotprompt.ts`**: The main entry point. Exports all sub-modules.
33
+ * **`src/recipes.ts`**: The **Recipes API** implementation (`cook` function). This is the high-level configuration layer that orchestrates the creation of prompts.
26
34
  * **`src/prompt.ts`**: Defines the `Prompt` interface and factory.
27
- * **`src/items/`**: Contains definitions for `Section`, `Instruction`, `Context`, `Content`.
28
- * **`src/loader.ts`**: Logic for loading prompt parts from the filesystem. It handles traversing directories and parsing Markdown files (extracting headers as section titles).
29
- * **`src/formatter.ts`**: Responsible for taking a `Prompt` object and converting it into a specific format (e.g., a Chat Request object or a flat string). It handles model-specific nuances via adapters.
35
+ * **`src/items/`**: Contains definitions for `Section` and various item types.
36
+ * **`src/loader.ts`**: Logic for loading prompt parts from the filesystem.
37
+ * **`src/formatter.ts`**: Responsible for taking a `Prompt` object and converting it into a specific format (e.g., a Chat Request object or a flat string). It handles model-specific rules via adapters.
38
+ * **`src/execution/`**: Contains provider implementations (OpenAI, Anthropic, Gemini) that handle API calls and structured output adaptation.
30
39
  * **`src/serializer.ts`**: Handles converting the internal `Prompt` structure to portable formats like JSON and XML.
31
- * **`src/cli.ts`**: The command-line interface implementation, using `commander` and `cardigantime` for config.
40
+ * **`src/cli.ts`**: The command-line interface implementation.
32
41
 
33
- ## Data Flow (CLI)
42
+ ## Data Flow (Recipes API)
34
43
 
35
- 1. **Input**: User provides a directory path.
36
- 2. **Loader**: `loader.ts` scans the directory.
37
- * `persona.md` or `persona/` -> `Section<Instruction>` (Persona)
38
- * `instructions.md` or `instructions/` -> `Section<Instruction>` (Instructions)
39
- * `context/` -> `Section<Context>` (Context)
44
+ 1. **Config**: User provides a `RecipeConfig` object (and optionally a template name).
45
+ 2. **Cook**: The `cook` function processes the config:
46
+ * Loads templates if specified.
47
+ * Merges overrides.
48
+ * Resolves file paths using `Loader`.
49
+ * Creates `Section` objects for each component (`persona`, `instructions`, etc.).
50
+ * Processes `zod` schemas for structured output.
40
51
  3. **Assembly**: Parts are combined into a `Prompt` object.
41
- 4. **Processing**:
42
- * If **Serialization** is requested: `Serializer` converts `Prompt` to JSON/XML.
43
- * If **Formatting** is requested: `Formatter` applies model-specific rules (e.g., role assignment) to generate a Chat Request.
44
- 5. **Output**: Result is written to stdout or file.
52
+ 4. **Execution**:
53
+ * `executeChat` takes the `Prompt`.
54
+ * `Formatter` converts it to the provider-specific format (handling roles, schema adaptation).
55
+ * Provider client sends request and returns result.
45
56
 
46
57
  ## Design Decisions
47
58
 
48
- * **Composition over Concatenation**: By keeping prompt parts separate until the final moment, we allow for dynamic injection, reordering, and model-specific formatting without string manipulation hell.
49
- * **FileSystem as Source**: We treat the filesystem as a primary way to organize complex prompts. Folders represent Sections, files represent Items. This makes prompts version-controllable and easy to navigate.
50
- * **Type Safety**: Extensive use of TypeScript generic types (`Section<T>`) ensures that we don't accidentally mix up Context (data) with Instructions (logic).
51
-
59
+ * **Configuration over Code**: The Recipes API favors declarative configuration over imperative builder patterns, making prompts easier to read and maintain.
60
+ * **Composition**: By keeping prompt parts separate until the final moment, we allow for dynamic injection, reordering, and model-specific formatting.
61
+ * **FileSystem as Source**: We treat the filesystem as a primary way to organize complex prompts. Folders represent Sections, files represent Items.
62
+ * **Portable Schemas**: We use `zod` as a universal schema definition language, adapting it to provider-specific formats (JSON Schema, Tools) at runtime to prevent vendor lock-in.
package/guide/index.md CHANGED
@@ -8,40 +8,41 @@
8
8
 
9
9
  `riotprompt` is a library and CLI tool designed to treat LLM prompts as structured code objects rather than simple strings. It allows for the modular assembly, validation, and formatting of prompts.
10
10
 
11
- * **Structured Prompts**: Prompts are composed of distinct sections: `Persona`, `Instructions`, `Context`, and `Content`.
12
- * **Modular Assembly**: Sections can be loaded from separate files or directories and combined dynamically.
13
- * **Model-Agnostic Formatting**: The library separates the *content* of a prompt from its *format*. It can output prompts optimized for different models (e.g., OpenAI, Claude) using adapters.
14
- * **Serialization**: Prompts can be serialized to JSON or XML for storage or exchange.
15
- * **CLI Tool**: A command-line interface allows for easy processing of prompt directories into formatted outputs.
11
+ * **Structured Prompts**: Prompts are composed of distinct sections beyond just "System" and "User". Use specialized sections like `Persona`, `Instructions`, `Constraints`, `Tone`, `Examples`, `Reasoning`, and more.
12
+ * **Recipes & Templates**: A declarative API (`cook`) allows you to assemble prompts from configuration objects and reusable templates.
13
+ * **Structured Outputs**: Portable support for structured outputs using `zod` schemas. Write one schema and use it across OpenAI, Anthropic, and Gemini.
14
+ * **Model-Agnostic Formatting**: The library separates the *content* of a prompt from its *format*. It can output prompts optimized for different models (e.g., handling role mapping for OpenAI's O-series vs GPT-4).
15
+ * **CLI Tool**: A command-line interface allows for easy scaffolding, processing, and execution of file-based prompts.
16
16
 
17
17
  ## Quick Start Context
18
18
 
19
19
  When analyzing or generating code using `riotprompt`, keep these patterns in mind:
20
20
 
21
- 1. **Define Sections**: Prompts are built from `Section<T>` objects.
22
- 2. **Create Prompt**: Use `createPrompt` to combine sections.
23
- 3. **Format**: Use `Formatter` to convert the structured prompt into a string or chat messages for a specific model.
21
+ 1. **Use Recipes**: The `cook` function is the primary entry point for creating prompts programmatically.
22
+ 2. **Use Schemas**: For structured data, pass a `zod` schema to `cook`.
23
+ 3. **Execute via Provider**: Use `executeChat` to run prompts against LLMs, handling provider-specific details automatically.
24
24
 
25
25
  ```typescript
26
- import * as RiotPrompt from '@riotprompt/riotprompt';
26
+ import { cook, executeChat } from '@riotprompt/riotprompt';
27
+ import { z } from 'zod';
27
28
 
28
- // 1. Create Sections
29
- const persona = RiotPrompt.createSection({ title: 'Persona' })
30
- .add(RiotPrompt.createInstruction('You are a helpful assistant.'));
31
-
32
- const instructions = RiotPrompt.createSection({ title: 'Instructions' })
33
- .add(RiotPrompt.createInstruction('Summarize the following text.'));
29
+ // Define output structure
30
+ const ResultSchema = z.object({
31
+ summary: z.string(),
32
+ tags: z.array(z.string())
33
+ });
34
34
 
35
- // 2. Create Prompt
36
- const prompt = RiotPrompt.createPrompt({
37
- persona,
38
- instructions
35
+ // Create prompt
36
+ const prompt = await cook({
37
+ basePath: __dirname,
38
+ persona: { content: 'You are a summarizer.' },
39
+ instructions: [{ content: 'Summarize the text.' }],
40
+ content: [{ content: 'Long text...' }],
41
+ schema: ResultSchema
39
42
  });
40
43
 
41
- // 3. Format
42
- const formatter = RiotPrompt.Formatter.create();
43
- // chatRequest will be a structured object suitable for API calls (e.g. OpenAI chat completion)
44
- const chatRequest = formatter.formatPrompt('gpt-4', prompt);
44
+ // Execute
45
+ const result = await executeChat(prompt, { model: 'gpt-4o' });
45
46
  ```
46
47
 
47
48
  ## Documentation Structure
@@ -49,7 +50,6 @@ const chatRequest = formatter.formatPrompt('gpt-4', prompt);
49
50
  This guide directory contains specialized documentation for different aspects of the system:
50
51
 
51
52
  * [Architecture](./architecture.md): Internal design, module structure, and data flow.
52
- * [Usage Patterns](./usage.md): Common patterns for CLI and library usage.
53
+ * [Usage Patterns](./usage.md): Common patterns for CLI and library usage, including the Recipes API and Structured Outputs.
53
54
  * [Configuration](./configuration.md): Deep dive into configuration options.
54
55
  * [Development](./development.md): Guide for contributing to `riotprompt`.
55
-
package/guide/usage.md CHANGED
@@ -8,15 +8,18 @@ The CLI is the primary way to interact with filesystem-based prompts.
8
8
 
9
9
  ### Directory Structure
10
10
 
11
- RiotPrompt expects a specific directory structure for a prompt "package":
11
+ RiotPrompt expects a specific directory structure for a prompt "package". You can now use expanded sections for more control:
12
12
 
13
13
  ```
14
14
  my-prompt-project/
15
15
  ├── persona.md # OR directory persona/ containing .md files
16
16
  ├── instructions.md # OR directory instructions/ containing .md files
17
- └── context/ # Directory containing reference files (json, md, txt)
18
- ├── data.json
19
- └── background.md
17
+ ├── context/ # Directory containing reference files (json, md, txt)
18
+ ├── data.json
19
+ └── background.md
20
+ ├── constraints.md # Optional: Operational constraints
21
+ ├── tone.md # Optional: Tone and style guidelines
22
+ └── examples.md # Optional: Few-shot examples
20
23
  ```
21
24
 
22
25
  ### Commands
@@ -48,52 +51,106 @@ riotprompt process ./my-prompt-project --format json --output prompt.json
48
51
  riotprompt process ./my-prompt-project --format xml --output prompt.xml
49
52
  ```
50
53
 
51
- ## Library Usage
54
+ ## Library Usage (Recipes API)
52
55
 
53
- You can import `riotprompt` into your own TypeScript applications to build dynamic prompt pipelines.
56
+ The primary way to use RiotPrompt programmatically is via the **Recipes API** (`cook` function). This provides a declarative, configuration-driven approach.
54
57
 
55
- ### Dynamic Context Injection
58
+ ### Basic Recipe
56
59
 
57
- A common pattern is to have static instructions but dynamic context (e.g., user data).
60
+ ```typescript
61
+ import { cook } from '@riotprompt/riotprompt';
62
+
63
+ const prompt = await cook({
64
+ basePath: __dirname,
65
+ persona: { content: 'You are a helpful AI assistant.' },
66
+ instructions: [
67
+ { content: 'Summarize the provided text.' }
68
+ ],
69
+ content: [
70
+ { content: 'Text to summarize goes here...' }
71
+ ]
72
+ });
73
+ ```
74
+
75
+ ### Expanded Prompt Sections
76
+
77
+ RiotPrompt now supports a wide range of specialized sections to give you fine-grained control over the prompt structure. These are inspired by advanced prompting techniques.
78
+
79
+ * **`persona`**: Who the AI is.
80
+ * **`instructions`**: What the AI should do.
81
+ * **`context`**: Background information.
82
+ * **`content`**: The specific input to process.
83
+ * **`constraints`**: Hard rules and limitations (e.g., "Do not use markdown").
84
+ * **`tone`**: Style and voice guidelines (e.g., "Be professional and concise").
85
+ * **`examples`**: Few-shot examples to guide the model.
86
+ * **`reasoning`**: Instructions on how to think (e.g., "Think step-by-step").
87
+ * **`responseFormat`**: Instructions on output structure.
88
+ * **`recap`**: Final reminders or summaries of instructions.
89
+ * **`safeguards`**: Safety guidelines and refusal criteria.
58
90
 
59
91
  ```typescript
60
- import * as RiotPrompt from '@riotprompt/riotprompt';
61
-
62
- async function buildPromptForUser(userData: any) {
63
- // 1. Load static parts from disk
64
- const loader = RiotPrompt.Loader.create();
65
- const [baseContext] = await loader.load(['./prompts/base-context']);
66
-
67
- // 2. Create dynamic sections
68
- const userContext = RiotPrompt.createSection({ title: 'User Data' });
69
- userContext.add(JSON.stringify(userData));
70
-
71
- // 3. Create Instructions
72
- const instructions = RiotPrompt.createSection({ title: 'Task' })
73
- .add(RiotPrompt.createInstruction('Analyze this user data.'));
74
-
75
- // 4. Assemble
76
- const prompt = RiotPrompt.createPrompt({
77
- instructions,
78
- contexts: RiotPrompt.createSection({ title: 'Context' })
79
- .add(baseContext)
80
- .add(userContext) // Inject dynamic part
81
- });
82
-
83
- return prompt;
84
- }
92
+ const prompt = await cook({
93
+ basePath: __dirname,
94
+ persona: { content: 'You are a senior code reviewer.' },
95
+ instructions: [{ content: 'Review this pull request.' }],
96
+ constraints: [{ content: 'Focus on security vulnerabilities.' }],
97
+ tone: [{ content: 'Constructive and empathetic.' }],
98
+ examples: [{ path: './examples/good-review.md' }],
99
+ content: [{ content: prDiff }]
100
+ });
85
101
  ```
86
102
 
87
- ### Custom Formatters
103
+ ### Structured Outputs (Portable Schemas)
88
104
 
89
- If you need to output to a specific non-standard format, you can access the raw `Prompt` object structure.
105
+ RiotPrompt supports portable structured outputs using `zod` schemas. This works across different providers (OpenAI, Anthropic, Gemini) by automatically adapting the schema to the provider's expected format (JSON Schema, Tool Use, etc.).
90
106
 
91
107
  ```typescript
92
- const prompt = ...;
108
+ import { cook, executeChat } from '@riotprompt/riotprompt';
109
+ import { z } from 'zod';
110
+
111
+ // 1. Define your schema using Zod
112
+ const AnalysisSchema = z.object({
113
+ sentiment: z.enum(['positive', 'negative', 'neutral']),
114
+ keyPoints: z.array(z.string()),
115
+ confidence: z.number().min(0).max(1)
116
+ });
117
+
118
+ // 2. Pass it to the cook function
119
+ const prompt = await cook({
120
+ basePath: __dirname,
121
+ persona: { content: 'You are a sentiment analyzer.' },
122
+ content: [{ content: 'I loved this movie! It was fantastic.' }],
123
+ schema: AnalysisSchema // Pass the Zod schema directly
124
+ });
93
125
 
94
- // Iterate over instructions
95
- prompt.instructions.items.forEach(item => {
96
- console.log(item.text);
126
+ // 3. Execute (RiotPrompt handles the provider specifics)
127
+ const result = await executeChat(prompt, {
128
+ model: 'gpt-4o', // or 'claude-3-opus', 'gemini-1.5-pro'
129
+ apiKey: process.env.OPENAI_API_KEY
97
130
  });
131
+
132
+ // result.content is validated and typed
133
+ console.log(result.content.sentiment); // "positive"
98
134
  ```
99
135
 
136
+ ### Templates
137
+
138
+ You can register reusable templates to standardize prompts across your application.
139
+
140
+ ```typescript
141
+ import { registerTemplates, cook } from '@riotprompt/riotprompt';
142
+
143
+ registerTemplates({
144
+ 'security-audit': {
145
+ persona: { content: 'You are a security auditor.' },
146
+ constraints: [{ content: 'Report only high-severity issues.' }],
147
+ responseFormat: [{ content: 'Output as a CSV list.' }]
148
+ }
149
+ });
150
+
151
+ const prompt = await cook({
152
+ basePath: __dirname,
153
+ template: 'security-audit',
154
+ content: [{ content: sourceCode }]
155
+ });
156
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riotprompt/riotprompt",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "keywords": [
5
5
  "prompt",
6
6
  "llm",
@@ -84,6 +84,7 @@
84
84
  "marked": "^16.0.0",
85
85
  "openai": "^6.15.0",
86
86
  "tiktoken": "^1.0.22",
87
- "zod": "^4.0.2"
87
+ "zod": "^4.0.2",
88
+ "zod-to-json-schema": "^3.25.1"
88
89
  }
89
90
  }