prompt-template-manager 1.0.0__tar.gz
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.
- prompt_template_manager-1.0.0/PKG-INFO +358 -0
- prompt_template_manager-1.0.0/README.md +332 -0
- prompt_template_manager-1.0.0/prompt_template_manager/Prompt.py +160 -0
- prompt_template_manager-1.0.0/prompt_template_manager/PromptManager.py +489 -0
- prompt_template_manager-1.0.0/prompt_template_manager/constants.py +64 -0
- prompt_template_manager-1.0.0/prompt_template_manager/sandbox.py +154 -0
- prompt_template_manager-1.0.0/prompt_template_manager.egg-info/PKG-INFO +358 -0
- prompt_template_manager-1.0.0/prompt_template_manager.egg-info/SOURCES.txt +11 -0
- prompt_template_manager-1.0.0/prompt_template_manager.egg-info/dependency_links.txt +1 -0
- prompt_template_manager-1.0.0/prompt_template_manager.egg-info/requires.txt +1 -0
- prompt_template_manager-1.0.0/prompt_template_manager.egg-info/top_level.txt +1 -0
- prompt_template_manager-1.0.0/setup.cfg +4 -0
- prompt_template_manager-1.0.0/setup.py +28 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prompt-template-manager
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight and extensible Python library for managing, versioning, and composing reusable prompt templates from YAML or text files.
|
|
5
|
+
Home-page: https://promptmanager.davman.dev
|
|
6
|
+
Author: Dave Manufor
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
10
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: PyYAML
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
# Prompt Manager
|
|
28
|
+
|
|
29
|
+
A robust **Python utility** for loading, versioning, and managing prompt templates from YAML files or flat file directories.
|
|
30
|
+
|
|
31
|
+
Prompt Manager is designed to solve the problem of managing a **large, complex, and evolving library of prompts**. It allows you to compose prompts from reusable parts, manage versions (e.g., for A/B testing or model-specific tuning), and safely inject variables at runtime.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 📚 Table of Contents
|
|
36
|
+
|
|
37
|
+
* [Core Features](#-core-features)
|
|
38
|
+
* [Installation](#-installation)
|
|
39
|
+
* [Quick Start](#-quick-start)
|
|
40
|
+
* [YAML Configuration Schema](#-yaml-configuration-schema)
|
|
41
|
+
|
|
42
|
+
* [Versioned Prompts (Recommended)](#1-versioned-prompts-recommended)
|
|
43
|
+
* [Simple Prompts (Non-versioned)](#2-simple-prompts-non-versioned)
|
|
44
|
+
* [Include Directives – {include prompt_name}](#3-include-directives--include-prompt_name)
|
|
45
|
+
* [Variable Placeholders – {variable_name}](#4-variable-placeholders--variable_name)
|
|
46
|
+
* [Loading from a Directory](#-loading-from-a-directory)
|
|
47
|
+
* [API Reference](#-api-reference)
|
|
48
|
+
|
|
49
|
+
* [Class: PromptManager](#class-promptmanager)
|
|
50
|
+
* [Class: Prompt](#class-prompt)
|
|
51
|
+
* [Advanced Usage Examples](#-advanced-usage-examples)
|
|
52
|
+
|
|
53
|
+
* [Example 1: Version A/B Testing](#example-1-version-ab-testing)
|
|
54
|
+
* [Example 2: Partial Formatting (Chain-of-Thought)](#example-2-partial-formatting-chain-of-thought)
|
|
55
|
+
* [Validation Rules](#-validation-rules)
|
|
56
|
+
* [Testing](#-testing)
|
|
57
|
+
* [License](#-license)
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🚀 Core Features
|
|
62
|
+
|
|
63
|
+
* **Centralized Prompt Management:** Load all prompts from a single structured YAML file.
|
|
64
|
+
* **Fallback Directory Loading:** Optionally load simple prompts from a directory of `.txt` files.
|
|
65
|
+
* **Prompt Versioning:** Native support for versions (e.g., `v1`, `v2`) with a `_default` key.
|
|
66
|
+
* **Recursive Composition:** Build complex prompts from smaller, reusable components using `{include ...}` directives.
|
|
67
|
+
* **Safe Variable Substitution:** Format prompts with `{variable}` placeholders using a strict or non-strict API.
|
|
68
|
+
* **Partial Formatting:** Fill variables incrementally for chain-of-thought or multi-step prompt sequences.
|
|
69
|
+
* **Configuration Validation:** Validate prompt configurations at load time to catch errors early.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 💾 Installation
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install prompt_template_manager
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## ⚡ Quick Start
|
|
82
|
+
|
|
83
|
+
### 1. Create your `prompts.yaml` file
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
# prompts.yaml
|
|
87
|
+
|
|
88
|
+
system_persona:
|
|
89
|
+
_default: v2
|
|
90
|
+
_meta:
|
|
91
|
+
description: "The standard AI persona."
|
|
92
|
+
v1: "You are a helpful AI."
|
|
93
|
+
v2: "You are a helpful, concise, and polite AI assistant."
|
|
94
|
+
|
|
95
|
+
summarize_task:
|
|
96
|
+
_default: v1
|
|
97
|
+
v1: |
|
|
98
|
+
{include system_persona}
|
|
99
|
+
|
|
100
|
+
Your task is to summarize the following document into {num_sentences} sentences.
|
|
101
|
+
Document: {text}
|
|
102
|
+
|
|
103
|
+
Your summary:
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. Use `PromptManager` in your Python code
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from source.PromptManager import PromptManager
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
manager = PromptManager('prompts.yaml')
|
|
113
|
+
prompt = manager.get('summarize_task')
|
|
114
|
+
|
|
115
|
+
my_data = {
|
|
116
|
+
"num_sentences": 3,
|
|
117
|
+
"text": "The quick brown fox jumps over the lazy dog."
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
formatted_prompt = prompt.format(my_data)
|
|
121
|
+
print(formatted_prompt)
|
|
122
|
+
|
|
123
|
+
except FileNotFoundError:
|
|
124
|
+
print("Error: prompts.yaml not found.")
|
|
125
|
+
except (ValueError, KeyError) as e:
|
|
126
|
+
print(f"Error loading or getting prompt: {e}")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Output:**
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
You are a helpful, concise, and polite AI assistant.
|
|
133
|
+
|
|
134
|
+
Your task is to summarize the following document into 3 sentences.
|
|
135
|
+
Document: The quick brown fox jumps over the lazy dog.
|
|
136
|
+
|
|
137
|
+
Your summary:
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🧩 YAML Configuration Schema
|
|
143
|
+
|
|
144
|
+
The `PromptManager` supports two main structures for defining prompts.
|
|
145
|
+
|
|
146
|
+
### 1. Versioned Prompts (Recommended)
|
|
147
|
+
|
|
148
|
+
A “versioned prompt” is a dictionary containing:
|
|
149
|
+
|
|
150
|
+
* `_default` (Required): Default version key (e.g., `v1`).
|
|
151
|
+
* `v{number}` (Required): Version key(s) with prompt text.
|
|
152
|
+
* `_meta` (Optional): Arbitrary metadata.
|
|
153
|
+
|
|
154
|
+
**Example:**
|
|
155
|
+
|
|
156
|
+
```yaml
|
|
157
|
+
system_persona_default:
|
|
158
|
+
_default: v2
|
|
159
|
+
_meta:
|
|
160
|
+
description: "The standard AI persona."
|
|
161
|
+
author: "Admin"
|
|
162
|
+
v1: "You are a helpful AI."
|
|
163
|
+
v2: "You are a helpful, concise, and polite AI assistant. You always answer the user's question directly."
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### 2. Simple Prompts (Non-versioned)
|
|
169
|
+
|
|
170
|
+
For simple, static prompts:
|
|
171
|
+
|
|
172
|
+
```yaml
|
|
173
|
+
simple_greeting: "Hello, {name}. This is a simple, non-versioned prompt."
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> ⚠️ Not recommended for complex systems — lacks versioning, metadata, and include support.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
### 3. Include Directives – `{include prompt_name}`
|
|
181
|
+
|
|
182
|
+
Compose prompts from other prompts:
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
system_persona:
|
|
186
|
+
_default: v1
|
|
187
|
+
v1: "You are a helpful AI."
|
|
188
|
+
|
|
189
|
+
output_format_json:
|
|
190
|
+
_default: v1
|
|
191
|
+
v1: "Your response MUST be a single, valid JSON object."
|
|
192
|
+
|
|
193
|
+
generate_user_profile:
|
|
194
|
+
_default: v1
|
|
195
|
+
_meta:
|
|
196
|
+
description: "Generates a JSON profile from a user's bio."
|
|
197
|
+
v1: |
|
|
198
|
+
{include system_persona}
|
|
199
|
+
{include output_format_json}
|
|
200
|
+
|
|
201
|
+
Analyze the following user bio and generate a profile.
|
|
202
|
+
Bio: {bio_text}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Circular references (e.g., A includes B and B includes A) raise an **ImportError**.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### 4. Variable Placeholders – `{variable_name}`
|
|
210
|
+
|
|
211
|
+
* Any text enclosed in `{}` is treated as a variable.
|
|
212
|
+
* Variables are filled using `.format()` or `.partial()`.
|
|
213
|
+
* Variable names are validated on load.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 📁 Loading from a Directory
|
|
218
|
+
|
|
219
|
+
You can also load prompts from a directory:
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
my_txt_prompts/
|
|
223
|
+
├── greet.txt
|
|
224
|
+
└── farewell.txt
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
manager = PromptManager('my_txt_prompts/')
|
|
229
|
+
prompt = manager.get('greet')
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Notes:**
|
|
233
|
+
|
|
234
|
+
* Only `.txt` files are loaded.
|
|
235
|
+
* Filenames become prompt names.
|
|
236
|
+
* Each prompt defaults to version `v1`.
|
|
237
|
+
* No support for metadata, includes, or multiple versions.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 🧠 API Reference
|
|
242
|
+
|
|
243
|
+
### **Class: `PromptManager`**
|
|
244
|
+
|
|
245
|
+
#### `__init__(self, source_path: str | Path)`
|
|
246
|
+
|
|
247
|
+
Loads and validates prompts from a YAML file or `.txt` directory.
|
|
248
|
+
|
|
249
|
+
**Raises:**
|
|
250
|
+
`FileNotFoundError`, `ValueError`, `yaml.YAMLError`
|
|
251
|
+
|
|
252
|
+
#### `get(self, name: str, version: int | None = None) -> Prompt`
|
|
253
|
+
|
|
254
|
+
Retrieves a fully resolved `Prompt` object.
|
|
255
|
+
|
|
256
|
+
**Raises:**
|
|
257
|
+
`KeyError`, `ValueError`, `ImportError`
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
### **Class: `Prompt`**
|
|
262
|
+
|
|
263
|
+
#### `format(self, data: dict, strict: bool = True) -> str`
|
|
264
|
+
|
|
265
|
+
Substitutes all variables.
|
|
266
|
+
|
|
267
|
+
#### `partial(self, data: dict) -> Prompt`
|
|
268
|
+
|
|
269
|
+
Partially fills variables, returning a new `Prompt`.
|
|
270
|
+
|
|
271
|
+
#### `get_raw_content(self) -> str`
|
|
272
|
+
|
|
273
|
+
Returns resolved, unformatted prompt text.
|
|
274
|
+
|
|
275
|
+
#### `get_variables(self) -> dict`
|
|
276
|
+
|
|
277
|
+
Lists remaining variable placeholders.
|
|
278
|
+
|
|
279
|
+
#### `get_meta(self) -> dict`
|
|
280
|
+
|
|
281
|
+
Returns the `_meta` dictionary (if any).
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## ⚙️ Advanced Usage Examples
|
|
286
|
+
|
|
287
|
+
### Example 1: Version A/B Testing
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
manager = PromptManager('prompts.yaml')
|
|
291
|
+
|
|
292
|
+
prompt_v2 = manager.get('system_persona')
|
|
293
|
+
prompt_v1 = manager.get('system_persona', version=1)
|
|
294
|
+
|
|
295
|
+
print(f"Default: {prompt_v2.get_raw_content()}")
|
|
296
|
+
print(f"V1: {prompt_v1.get_raw_content()}")
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Output:**
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
Default: You are a helpful, concise, and polite AI assistant.
|
|
303
|
+
V1: You are a helpful AI.
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
### Example 2: Partial Formatting (Chain-of-Thought)
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
manager = PromptManager('prompts.yaml')
|
|
312
|
+
prompt = manager.get('summarize_task')
|
|
313
|
+
|
|
314
|
+
print(f"Original variables: {prompt.get_variables().keys()}")
|
|
315
|
+
|
|
316
|
+
partial_prompt = prompt.partial({
|
|
317
|
+
"text": "This is a long document about the history of computing."
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
print(f"Partial variables: {partial_prompt.get_variables().keys()}")
|
|
321
|
+
print("--- Partial Content ---")
|
|
322
|
+
print(partial_prompt.get_raw_content())
|
|
323
|
+
|
|
324
|
+
final_prompt_str = partial_prompt.format({
|
|
325
|
+
"num_sentences": 2
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
print("\n--- Final Content ---")
|
|
329
|
+
print(final_prompt_str)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## ✅ Validation Rules
|
|
335
|
+
|
|
336
|
+
**Prompt Names**
|
|
337
|
+
|
|
338
|
+
* Must be valid Python identifiers (e.g., `my_prompt`, `_internal_prompt`).
|
|
339
|
+
|
|
340
|
+
**Variable Names**
|
|
341
|
+
|
|
342
|
+
* Must start with a letter.
|
|
343
|
+
* May include letters, numbers, `-`, and `_`.
|
|
344
|
+
* Cannot end with `-` or `_`.
|
|
345
|
+
|
|
346
|
+
**Include Names**
|
|
347
|
+
|
|
348
|
+
* Follow the same rules as variable names.
|
|
349
|
+
|
|
350
|
+
Invalid configurations raise `ValueError` during load.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## 🧰 License
|
|
355
|
+
|
|
356
|
+
MIT License — Prompt Manager Contributors
|
|
357
|
+
|
|
358
|
+
---
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# Prompt Manager
|
|
2
|
+
|
|
3
|
+
A robust **Python utility** for loading, versioning, and managing prompt templates from YAML files or flat file directories.
|
|
4
|
+
|
|
5
|
+
Prompt Manager is designed to solve the problem of managing a **large, complex, and evolving library of prompts**. It allows you to compose prompts from reusable parts, manage versions (e.g., for A/B testing or model-specific tuning), and safely inject variables at runtime.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📚 Table of Contents
|
|
10
|
+
|
|
11
|
+
* [Core Features](#-core-features)
|
|
12
|
+
* [Installation](#-installation)
|
|
13
|
+
* [Quick Start](#-quick-start)
|
|
14
|
+
* [YAML Configuration Schema](#-yaml-configuration-schema)
|
|
15
|
+
|
|
16
|
+
* [Versioned Prompts (Recommended)](#1-versioned-prompts-recommended)
|
|
17
|
+
* [Simple Prompts (Non-versioned)](#2-simple-prompts-non-versioned)
|
|
18
|
+
* [Include Directives – {include prompt_name}](#3-include-directives--include-prompt_name)
|
|
19
|
+
* [Variable Placeholders – {variable_name}](#4-variable-placeholders--variable_name)
|
|
20
|
+
* [Loading from a Directory](#-loading-from-a-directory)
|
|
21
|
+
* [API Reference](#-api-reference)
|
|
22
|
+
|
|
23
|
+
* [Class: PromptManager](#class-promptmanager)
|
|
24
|
+
* [Class: Prompt](#class-prompt)
|
|
25
|
+
* [Advanced Usage Examples](#-advanced-usage-examples)
|
|
26
|
+
|
|
27
|
+
* [Example 1: Version A/B Testing](#example-1-version-ab-testing)
|
|
28
|
+
* [Example 2: Partial Formatting (Chain-of-Thought)](#example-2-partial-formatting-chain-of-thought)
|
|
29
|
+
* [Validation Rules](#-validation-rules)
|
|
30
|
+
* [Testing](#-testing)
|
|
31
|
+
* [License](#-license)
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 🚀 Core Features
|
|
36
|
+
|
|
37
|
+
* **Centralized Prompt Management:** Load all prompts from a single structured YAML file.
|
|
38
|
+
* **Fallback Directory Loading:** Optionally load simple prompts from a directory of `.txt` files.
|
|
39
|
+
* **Prompt Versioning:** Native support for versions (e.g., `v1`, `v2`) with a `_default` key.
|
|
40
|
+
* **Recursive Composition:** Build complex prompts from smaller, reusable components using `{include ...}` directives.
|
|
41
|
+
* **Safe Variable Substitution:** Format prompts with `{variable}` placeholders using a strict or non-strict API.
|
|
42
|
+
* **Partial Formatting:** Fill variables incrementally for chain-of-thought or multi-step prompt sequences.
|
|
43
|
+
* **Configuration Validation:** Validate prompt configurations at load time to catch errors early.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 💾 Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install prompt_template_manager
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## ⚡ Quick Start
|
|
56
|
+
|
|
57
|
+
### 1. Create your `prompts.yaml` file
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
# prompts.yaml
|
|
61
|
+
|
|
62
|
+
system_persona:
|
|
63
|
+
_default: v2
|
|
64
|
+
_meta:
|
|
65
|
+
description: "The standard AI persona."
|
|
66
|
+
v1: "You are a helpful AI."
|
|
67
|
+
v2: "You are a helpful, concise, and polite AI assistant."
|
|
68
|
+
|
|
69
|
+
summarize_task:
|
|
70
|
+
_default: v1
|
|
71
|
+
v1: |
|
|
72
|
+
{include system_persona}
|
|
73
|
+
|
|
74
|
+
Your task is to summarize the following document into {num_sentences} sentences.
|
|
75
|
+
Document: {text}
|
|
76
|
+
|
|
77
|
+
Your summary:
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Use `PromptManager` in your Python code
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from source.PromptManager import PromptManager
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
manager = PromptManager('prompts.yaml')
|
|
87
|
+
prompt = manager.get('summarize_task')
|
|
88
|
+
|
|
89
|
+
my_data = {
|
|
90
|
+
"num_sentences": 3,
|
|
91
|
+
"text": "The quick brown fox jumps over the lazy dog."
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
formatted_prompt = prompt.format(my_data)
|
|
95
|
+
print(formatted_prompt)
|
|
96
|
+
|
|
97
|
+
except FileNotFoundError:
|
|
98
|
+
print("Error: prompts.yaml not found.")
|
|
99
|
+
except (ValueError, KeyError) as e:
|
|
100
|
+
print(f"Error loading or getting prompt: {e}")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Output:**
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
You are a helpful, concise, and polite AI assistant.
|
|
107
|
+
|
|
108
|
+
Your task is to summarize the following document into 3 sentences.
|
|
109
|
+
Document: The quick brown fox jumps over the lazy dog.
|
|
110
|
+
|
|
111
|
+
Your summary:
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 🧩 YAML Configuration Schema
|
|
117
|
+
|
|
118
|
+
The `PromptManager` supports two main structures for defining prompts.
|
|
119
|
+
|
|
120
|
+
### 1. Versioned Prompts (Recommended)
|
|
121
|
+
|
|
122
|
+
A “versioned prompt” is a dictionary containing:
|
|
123
|
+
|
|
124
|
+
* `_default` (Required): Default version key (e.g., `v1`).
|
|
125
|
+
* `v{number}` (Required): Version key(s) with prompt text.
|
|
126
|
+
* `_meta` (Optional): Arbitrary metadata.
|
|
127
|
+
|
|
128
|
+
**Example:**
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
system_persona_default:
|
|
132
|
+
_default: v2
|
|
133
|
+
_meta:
|
|
134
|
+
description: "The standard AI persona."
|
|
135
|
+
author: "Admin"
|
|
136
|
+
v1: "You are a helpful AI."
|
|
137
|
+
v2: "You are a helpful, concise, and polite AI assistant. You always answer the user's question directly."
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 2. Simple Prompts (Non-versioned)
|
|
143
|
+
|
|
144
|
+
For simple, static prompts:
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
simple_greeting: "Hello, {name}. This is a simple, non-versioned prompt."
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
> ⚠️ Not recommended for complex systems — lacks versioning, metadata, and include support.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### 3. Include Directives – `{include prompt_name}`
|
|
155
|
+
|
|
156
|
+
Compose prompts from other prompts:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
system_persona:
|
|
160
|
+
_default: v1
|
|
161
|
+
v1: "You are a helpful AI."
|
|
162
|
+
|
|
163
|
+
output_format_json:
|
|
164
|
+
_default: v1
|
|
165
|
+
v1: "Your response MUST be a single, valid JSON object."
|
|
166
|
+
|
|
167
|
+
generate_user_profile:
|
|
168
|
+
_default: v1
|
|
169
|
+
_meta:
|
|
170
|
+
description: "Generates a JSON profile from a user's bio."
|
|
171
|
+
v1: |
|
|
172
|
+
{include system_persona}
|
|
173
|
+
{include output_format_json}
|
|
174
|
+
|
|
175
|
+
Analyze the following user bio and generate a profile.
|
|
176
|
+
Bio: {bio_text}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Circular references (e.g., A includes B and B includes A) raise an **ImportError**.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### 4. Variable Placeholders – `{variable_name}`
|
|
184
|
+
|
|
185
|
+
* Any text enclosed in `{}` is treated as a variable.
|
|
186
|
+
* Variables are filled using `.format()` or `.partial()`.
|
|
187
|
+
* Variable names are validated on load.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 📁 Loading from a Directory
|
|
192
|
+
|
|
193
|
+
You can also load prompts from a directory:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
my_txt_prompts/
|
|
197
|
+
├── greet.txt
|
|
198
|
+
└── farewell.txt
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
manager = PromptManager('my_txt_prompts/')
|
|
203
|
+
prompt = manager.get('greet')
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Notes:**
|
|
207
|
+
|
|
208
|
+
* Only `.txt` files are loaded.
|
|
209
|
+
* Filenames become prompt names.
|
|
210
|
+
* Each prompt defaults to version `v1`.
|
|
211
|
+
* No support for metadata, includes, or multiple versions.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 🧠 API Reference
|
|
216
|
+
|
|
217
|
+
### **Class: `PromptManager`**
|
|
218
|
+
|
|
219
|
+
#### `__init__(self, source_path: str | Path)`
|
|
220
|
+
|
|
221
|
+
Loads and validates prompts from a YAML file or `.txt` directory.
|
|
222
|
+
|
|
223
|
+
**Raises:**
|
|
224
|
+
`FileNotFoundError`, `ValueError`, `yaml.YAMLError`
|
|
225
|
+
|
|
226
|
+
#### `get(self, name: str, version: int | None = None) -> Prompt`
|
|
227
|
+
|
|
228
|
+
Retrieves a fully resolved `Prompt` object.
|
|
229
|
+
|
|
230
|
+
**Raises:**
|
|
231
|
+
`KeyError`, `ValueError`, `ImportError`
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### **Class: `Prompt`**
|
|
236
|
+
|
|
237
|
+
#### `format(self, data: dict, strict: bool = True) -> str`
|
|
238
|
+
|
|
239
|
+
Substitutes all variables.
|
|
240
|
+
|
|
241
|
+
#### `partial(self, data: dict) -> Prompt`
|
|
242
|
+
|
|
243
|
+
Partially fills variables, returning a new `Prompt`.
|
|
244
|
+
|
|
245
|
+
#### `get_raw_content(self) -> str`
|
|
246
|
+
|
|
247
|
+
Returns resolved, unformatted prompt text.
|
|
248
|
+
|
|
249
|
+
#### `get_variables(self) -> dict`
|
|
250
|
+
|
|
251
|
+
Lists remaining variable placeholders.
|
|
252
|
+
|
|
253
|
+
#### `get_meta(self) -> dict`
|
|
254
|
+
|
|
255
|
+
Returns the `_meta` dictionary (if any).
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## ⚙️ Advanced Usage Examples
|
|
260
|
+
|
|
261
|
+
### Example 1: Version A/B Testing
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
manager = PromptManager('prompts.yaml')
|
|
265
|
+
|
|
266
|
+
prompt_v2 = manager.get('system_persona')
|
|
267
|
+
prompt_v1 = manager.get('system_persona', version=1)
|
|
268
|
+
|
|
269
|
+
print(f"Default: {prompt_v2.get_raw_content()}")
|
|
270
|
+
print(f"V1: {prompt_v1.get_raw_content()}")
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Output:**
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
Default: You are a helpful, concise, and polite AI assistant.
|
|
277
|
+
V1: You are a helpful AI.
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
### Example 2: Partial Formatting (Chain-of-Thought)
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
manager = PromptManager('prompts.yaml')
|
|
286
|
+
prompt = manager.get('summarize_task')
|
|
287
|
+
|
|
288
|
+
print(f"Original variables: {prompt.get_variables().keys()}")
|
|
289
|
+
|
|
290
|
+
partial_prompt = prompt.partial({
|
|
291
|
+
"text": "This is a long document about the history of computing."
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
print(f"Partial variables: {partial_prompt.get_variables().keys()}")
|
|
295
|
+
print("--- Partial Content ---")
|
|
296
|
+
print(partial_prompt.get_raw_content())
|
|
297
|
+
|
|
298
|
+
final_prompt_str = partial_prompt.format({
|
|
299
|
+
"num_sentences": 2
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
print("\n--- Final Content ---")
|
|
303
|
+
print(final_prompt_str)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## ✅ Validation Rules
|
|
309
|
+
|
|
310
|
+
**Prompt Names**
|
|
311
|
+
|
|
312
|
+
* Must be valid Python identifiers (e.g., `my_prompt`, `_internal_prompt`).
|
|
313
|
+
|
|
314
|
+
**Variable Names**
|
|
315
|
+
|
|
316
|
+
* Must start with a letter.
|
|
317
|
+
* May include letters, numbers, `-`, and `_`.
|
|
318
|
+
* Cannot end with `-` or `_`.
|
|
319
|
+
|
|
320
|
+
**Include Names**
|
|
321
|
+
|
|
322
|
+
* Follow the same rules as variable names.
|
|
323
|
+
|
|
324
|
+
Invalid configurations raise `ValueError` during load.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 🧰 License
|
|
329
|
+
|
|
330
|
+
MIT License — Prompt Manager Contributors
|
|
331
|
+
|
|
332
|
+
---
|