instructvault 0.2.8__tar.gz → 0.3.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.
Files changed (76) hide show
  1. instructvault-0.3.0/.gitignore +17 -0
  2. {instructvault-0.2.8 → instructvault-0.3.0}/PKG-INFO +17 -1
  3. {instructvault-0.2.8 → instructvault-0.3.0}/README.md +15 -0
  4. instructvault-0.3.0/docs/assets/logo.png +0 -0
  5. instructvault-0.3.0/docs/audit_logging.md +25 -0
  6. {instructvault-0.2.8 → instructvault-0.3.0}/docs/cookbooks.md +39 -0
  7. instructvault-0.3.0/docs/spec.md +40 -0
  8. instructvault-0.3.0/examples/notebooks/instructvault_colab.ipynb +128 -0
  9. instructvault-0.3.0/examples/notebooks/instructvault_openai_colab.ipynb +112 -0
  10. instructvault-0.3.0/examples/notebooks/instructvault_rag_colab.ipynb +127 -0
  11. instructvault-0.3.0/examples/policies/policy_example.py +14 -0
  12. instructvault-0.3.0/examples/policies/policy_pack.py +26 -0
  13. {instructvault-0.2.8 → instructvault-0.3.0}/pyproject.toml +2 -1
  14. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/cli.py +53 -8
  15. instructvault-0.3.0/src/instructvault/eval.py +80 -0
  16. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/io.py +9 -0
  17. instructvault-0.3.0/src/instructvault/policy.py +33 -0
  18. instructvault-0.3.0/src/instructvault/render.py +57 -0
  19. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/sdk.py +3 -3
  20. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/spec.py +4 -1
  21. {instructvault-0.2.8 → instructvault-0.3.0}/tests/test_cli_basic.py +34 -0
  22. instructvault-0.3.0/tests/test_eval_asserts.py +28 -0
  23. instructvault-0.2.8/src/instructvault/eval.py +0 -53
  24. instructvault-0.2.8/src/instructvault/render.py +0 -22
  25. {instructvault-0.2.8 → instructvault-0.3.0}/.github/CODEOWNERS +0 -0
  26. {instructvault-0.2.8 → instructvault-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  27. {instructvault-0.2.8 → instructvault-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  28. {instructvault-0.2.8 → instructvault-0.3.0}/.github/pull_request_template.md +0 -0
  29. {instructvault-0.2.8 → instructvault-0.3.0}/.github/workflows/ci.yml +0 -0
  30. {instructvault-0.2.8 → instructvault-0.3.0}/.github/workflows/prompt-checks.yml +0 -0
  31. {instructvault-0.2.8 → instructvault-0.3.0}/.github/workflows/release.yml +0 -0
  32. {instructvault-0.2.8 → instructvault-0.3.0}/CHANGELOG.md +0 -0
  33. {instructvault-0.2.8 → instructvault-0.3.0}/CODE_OF_CONDUCT.md +0 -0
  34. {instructvault-0.2.8 → instructvault-0.3.0}/CONTRIBUTING.md +0 -0
  35. {instructvault-0.2.8 → instructvault-0.3.0}/LICENSE +0 -0
  36. {instructvault-0.2.8 → instructvault-0.3.0}/SECURITY.md +0 -0
  37. {instructvault-0.2.8 → instructvault-0.3.0}/docs/assets/logo.svg +0 -0
  38. {instructvault-0.2.8 → instructvault-0.3.0}/docs/assets/logo_dark.png +0 -0
  39. {instructvault-0.2.8 → instructvault-0.3.0}/docs/assets/logo_dark.svg +0 -0
  40. {instructvault-0.2.8 → instructvault-0.3.0}/docs/assets/logo_light.svg +0 -0
  41. {instructvault-0.2.8 → instructvault-0.3.0}/docs/assets/playground.png +0 -0
  42. {instructvault-0.2.8 → instructvault-0.3.0}/docs/ci.md +0 -0
  43. {instructvault-0.2.8 → instructvault-0.3.0}/docs/ci_templates/Jenkinsfile +0 -0
  44. {instructvault-0.2.8 → instructvault-0.3.0}/docs/ci_templates/gitlab-ci.yml +0 -0
  45. {instructvault-0.2.8 → instructvault-0.3.0}/docs/dropin_guide.md +0 -0
  46. {instructvault-0.2.8 → instructvault-0.3.0}/docs/governance.md +0 -0
  47. {instructvault-0.2.8 → instructvault-0.3.0}/docs/playground.md +0 -0
  48. {instructvault-0.2.8 → instructvault-0.3.0}/docs/release_checklist.md +0 -0
  49. {instructvault-0.2.8 → instructvault-0.3.0}/docs/templates/CODEOWNERS +0 -0
  50. {instructvault-0.2.8 → instructvault-0.3.0}/docs/vision.md +0 -0
  51. {instructvault-0.2.8 → instructvault-0.3.0}/examples/datasets/classifier_cases.jsonl +0 -0
  52. {instructvault-0.2.8 → instructvault-0.3.0}/examples/datasets/rag_agent_cases.jsonl +0 -0
  53. {instructvault-0.2.8 → instructvault-0.3.0}/examples/datasets/rag_answer_cases.jsonl +0 -0
  54. {instructvault-0.2.8 → instructvault-0.3.0}/examples/datasets/support_cases.jsonl +0 -0
  55. {instructvault-0.2.8 → instructvault-0.3.0}/examples/prompts/classifier.prompt.yml +0 -0
  56. {instructvault-0.2.8 → instructvault-0.3.0}/examples/prompts/guardrail.prompt.json +0 -0
  57. {instructvault-0.2.8 → instructvault-0.3.0}/examples/prompts/hello_world.prompt.yml +0 -0
  58. {instructvault-0.2.8 → instructvault-0.3.0}/examples/prompts/rag_agent.prompt.yml +0 -0
  59. {instructvault-0.2.8 → instructvault-0.3.0}/examples/prompts/rag_answer.prompt.yml +0 -0
  60. {instructvault-0.2.8 → instructvault-0.3.0}/examples/prompts/support_reply.prompt.yml +0 -0
  61. {instructvault-0.2.8 → instructvault-0.3.0}/playground/README.md +0 -0
  62. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/__init__.py +0 -0
  63. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/app.py +0 -0
  64. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/routes/api.py +0 -0
  65. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/routes/ui.py +0 -0
  66. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/static/app.css +0 -0
  67. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/static/app.js +0 -0
  68. {instructvault-0.2.8 → instructvault-0.3.0}/playground/ivault_playground/templates/index.html +0 -0
  69. {instructvault-0.2.8 → instructvault-0.3.0}/playground/pyproject.toml +0 -0
  70. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/__init__.py +0 -0
  71. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/bundle.py +0 -0
  72. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/diff.py +0 -0
  73. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/junit.py +0 -0
  74. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/scaffold.py +0 -0
  75. {instructvault-0.2.8 → instructvault-0.3.0}/src/instructvault/store.py +0 -0
  76. {instructvault-0.2.8 → instructvault-0.3.0}/tests/test_playground_api.py +0 -0
@@ -0,0 +1,17 @@
1
+ .DS_Store
2
+ *.log
3
+ *.swp
4
+ .env
5
+
6
+ __pycache__/
7
+ *.pyc
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .ruff_cache/
11
+
12
+ .venv/
13
+ venv/
14
+
15
+ build/
16
+ dist/
17
+ *.egg-info/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instructvault
3
- Version: 0.2.8
3
+ Version: 0.3.0
4
4
  Summary: Git-first prompt registry + CI evals + lightweight runtime SDK (ivault).
5
5
  Project-URL: Homepage, https://github.com/05satyam/instruct_vault
6
6
  Project-URL: Repository, https://github.com/05satyam/instruct_vault
@@ -9,6 +9,7 @@ License: Apache-2.0
9
9
  License-File: LICENSE
10
10
  Requires-Python: >=3.10
11
11
  Requires-Dist: jinja2>=3.1
12
+ Requires-Dist: jsonschema>=4.21
12
13
  Requires-Dist: pydantic>=2.7
13
14
  Requires-Dist: pyyaml>=6.0
14
15
  Requires-Dist: rich>=13.7
@@ -127,6 +128,10 @@ ivault validate prompts
127
128
  ivault render prompts/support_reply.prompt.yml --vars '{"ticket_text":"My app crashed.","customer_name":"Sam"}'
128
129
  ```
129
130
 
131
+ Safety tip: add `--safe` to scan rendered output for common secret patterns.
132
+ Use `--strict-vars` to forbid unknown vars and `--redact` to mask detected secrets.
133
+ Use `--policy /path/to/policy.py` to enforce custom compliance rules.
134
+
130
135
  ### 4) Add dataset‑driven eval
131
136
  `datasets/support_cases.jsonl`
132
137
  ```jsonl
@@ -142,6 +147,11 @@ Note: Prompts must include at least one inline test. Datasets are optional.
142
147
  Migration tip: if you need to render a prompt that doesn’t yet include tests, use
143
148
  `ivault render --allow-no-tests` or add a minimal test first.
144
149
 
150
+ Spec migration check:
151
+ ```bash
152
+ ivault migrate prompts
153
+ ```
154
+
145
155
  ### 5) Version prompts with tags
146
156
  ```bash
147
157
  git add prompts datasets
@@ -179,6 +189,10 @@ vault = InstructVault(bundle_path="out/ivault.bundle.json")
179
189
  - `examples/notebooks/instructvault_openai_colab.ipynb`
180
190
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/05satyam/instruct_vault/blob/main/examples/notebooks/instructvault_openai_colab.ipynb)
181
191
 
192
+ ## Example Policies
193
+ - `examples/policies/policy_example.py`
194
+ - `examples/policies/policy_pack.py`
195
+
182
196
  ## How teams use this in production
183
197
  1) Prompt changes go through PRs
184
198
  2) CI runs `validate` + `eval`
@@ -208,11 +222,13 @@ Then send `x-ivault-api-key` in requests (or keep it behind your org gateway).
208
222
  If you don’t set the env var, no auth is required.
209
223
 
210
224
  ## Docs
225
+ - `docs/spec.md`
211
226
  - `docs/vision.md`
212
227
  - `docs/governance.md`
213
228
  - `docs/ci.md`
214
229
  - `docs/playground.md`
215
230
  - `docs/cookbooks.md`
231
+ - `docs/audit_logging.md`
216
232
  - `docs/dropin_guide.md`
217
233
  - `docs/release_checklist.md`
218
234
  - `docs/ci_templates/gitlab-ci.yml`
@@ -102,6 +102,10 @@ ivault validate prompts
102
102
  ivault render prompts/support_reply.prompt.yml --vars '{"ticket_text":"My app crashed.","customer_name":"Sam"}'
103
103
  ```
104
104
 
105
+ Safety tip: add `--safe` to scan rendered output for common secret patterns.
106
+ Use `--strict-vars` to forbid unknown vars and `--redact` to mask detected secrets.
107
+ Use `--policy /path/to/policy.py` to enforce custom compliance rules.
108
+
105
109
  ### 4) Add dataset‑driven eval
106
110
  `datasets/support_cases.jsonl`
107
111
  ```jsonl
@@ -117,6 +121,11 @@ Note: Prompts must include at least one inline test. Datasets are optional.
117
121
  Migration tip: if you need to render a prompt that doesn’t yet include tests, use
118
122
  `ivault render --allow-no-tests` or add a minimal test first.
119
123
 
124
+ Spec migration check:
125
+ ```bash
126
+ ivault migrate prompts
127
+ ```
128
+
120
129
  ### 5) Version prompts with tags
121
130
  ```bash
122
131
  git add prompts datasets
@@ -154,6 +163,10 @@ vault = InstructVault(bundle_path="out/ivault.bundle.json")
154
163
  - `examples/notebooks/instructvault_openai_colab.ipynb`
155
164
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/05satyam/instruct_vault/blob/main/examples/notebooks/instructvault_openai_colab.ipynb)
156
165
 
166
+ ## Example Policies
167
+ - `examples/policies/policy_example.py`
168
+ - `examples/policies/policy_pack.py`
169
+
157
170
  ## How teams use this in production
158
171
  1) Prompt changes go through PRs
159
172
  2) CI runs `validate` + `eval`
@@ -183,11 +196,13 @@ Then send `x-ivault-api-key` in requests (or keep it behind your org gateway).
183
196
  If you don’t set the env var, no auth is required.
184
197
 
185
198
  ## Docs
199
+ - `docs/spec.md`
186
200
  - `docs/vision.md`
187
201
  - `docs/governance.md`
188
202
  - `docs/ci.md`
189
203
  - `docs/playground.md`
190
204
  - `docs/cookbooks.md`
205
+ - `docs/audit_logging.md`
191
206
  - `docs/dropin_guide.md`
192
207
  - `docs/release_checklist.md`
193
208
  - `docs/ci_templates/gitlab-ci.yml`
Binary file
@@ -0,0 +1,25 @@
1
+ # Audit Logging (recommended)
2
+
3
+ Log these fields for every render/eval execution:
4
+ - prompt path
5
+ - git ref or SHA
6
+ - spec_version
7
+ - dataset path (if any)
8
+ - policy module (if any)
9
+ - safe / strict-vars / redact flags
10
+ - timestamp
11
+
12
+ Example payload:
13
+ ```
14
+ {
15
+ "prompt": "prompts/support_reply.prompt.yml",
16
+ "ref": "prompts/v1.2.0",
17
+ "spec_version": "1.0",
18
+ "dataset": "datasets/support_cases.jsonl",
19
+ "policy": "docs/policy_pack.py",
20
+ "safe": true,
21
+ "strict_vars": true,
22
+ "redact": true,
23
+ "timestamp": "2026-02-02T12:00:00Z"
24
+ }
25
+ ```
@@ -133,3 +133,42 @@ GitHub Actions snippet:
133
133
  Notes:
134
134
  - The dataset is still local when `ivault` runs.
135
135
  - Keep dataset files versioned or checksum-locked for reproducibility.
136
+
137
+ ## 12) Policy hooks (compliance / PII)
138
+ Create a policy module and pass it to `ivault`:
139
+ ```bash
140
+ ivault validate prompts --policy examples/policies/policy_example.py
141
+ ivault eval prompts/support_reply.prompt.yml --policy examples/policies/policy_example.py
142
+ ```
143
+
144
+ Default policy pack (simple PII + forbidden phrases):
145
+ ```bash
146
+ ivault validate prompts --policy examples/policies/policy_pack.py
147
+ ivault eval prompts/support_reply.prompt.yml --policy examples/policies/policy_pack.py
148
+ ```
149
+
150
+ ## 13) Custom evals (your own rules)
151
+ You can run your own checks using the SDK:
152
+ ```python
153
+ from instructvault import InstructVault
154
+
155
+ vault = InstructVault(repo_root=".")
156
+ msgs = vault.render("prompts/support_reply.prompt.yml", vars={"ticket_text":"Order delayed"})
157
+
158
+ # Custom checks here
159
+ assert any("Ticket:" in m.content for m in msgs)
160
+ ```
161
+
162
+ Or plug in a policy module:
163
+ ```bash
164
+ ivault eval prompts/support_reply.prompt.yml --policy my_policy.py
165
+ ```
166
+
167
+ Policy module signature:
168
+ ```python
169
+ def check_spec(spec: dict) -> list[str]:
170
+ return []
171
+
172
+ def check_render(text: str, context: dict) -> list[str]:
173
+ return []
174
+ ```
@@ -0,0 +1,40 @@
1
+ # Spec Contract
2
+
3
+ ## Versioning
4
+ - `spec_version` is required for prompts.
5
+ - Current stable series: **1.x**
6
+ - Minor versions (1.1, 1.2, …) must remain backward compatible with 1.0.
7
+ - Breaking changes require a major version (2.0).
8
+
9
+ ## Deprecation
10
+ - Deprecated fields must continue to parse for at least one minor release.
11
+ - Deprecations are documented in `CHANGELOG.md`.
12
+
13
+ ## Migration
14
+ Use:
15
+ ```
16
+ ivault migrate prompts
17
+ ```
18
+ This checks for missing `spec_version` and reports any files that need updates.
19
+ Use `--apply` to write `spec_version: 1.0` into YAML prompts.
20
+
21
+ ## Data Model (1.0)
22
+ Required:
23
+ - `spec_version`
24
+ - `name`
25
+ - `messages`
26
+ - `tests` (at least one inline test)
27
+
28
+ Optional:
29
+ - `description`
30
+ - `modelParameters` (alias: `model_defaults`)
31
+ - `variables`
32
+
33
+ ## Tests
34
+ Each test must include at least one assertion:
35
+ - `contains_any`
36
+ - `contains_all`
37
+ - `not_contains`
38
+ - `matches` (regex)
39
+ - `not_matches` (regex)
40
+ - `json_schema` (JSON Schema validation)
@@ -0,0 +1,128 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "e4b28969",
6
+ "metadata": {},
7
+ "source": [
8
+ "# InstructVault Quickstart (Google Colab)\n",
9
+ "\n",
10
+ "This notebook is designed for Colab. It uses `/content/ivault_demo` and repo-relative prompt paths."
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "id": "79ef050d",
17
+ "metadata": {},
18
+ "outputs": [],
19
+ "source": [
20
+ "!pip -q install instructvault\n"
21
+ ]
22
+ },
23
+ {
24
+ "cell_type": "code",
25
+ "execution_count": null,
26
+ "id": "d416a2e3",
27
+ "metadata": {},
28
+ "outputs": [],
29
+ "source": [
30
+ "# If you're not on Colab, change this path to your local repo folder.\n",
31
+ "repo_path = \"/content/ivault_demo\"\n",
32
+ "print(\"Using repo_path:\", repo_path)"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": null,
38
+ "id": "5c257338",
39
+ "metadata": {},
40
+ "outputs": [],
41
+ "source": [
42
+ "from pathlib import Path\n",
43
+ "\n",
44
+ "repo = Path(\"/content/content/ivault_demo\")\n",
45
+ "(repo / \"prompts\").mkdir(parents=True, exist_ok=True)\n",
46
+ "\n",
47
+ "prompt_text = '''spec_version: \"1.0\"\n",
48
+ "name: hello_world\n",
49
+ "variables:\n",
50
+ " required: [name]\n",
51
+ "messages:\n",
52
+ " - role: system\n",
53
+ " content: \"You are a helpful assistant.\"\n",
54
+ " - role: user\n",
55
+ " content: \"Say hello to {{ name }}.\"\n",
56
+ "tests:\n",
57
+ " - name: includes_name\n",
58
+ " vars: { name: \"Ava\" }\n",
59
+ " assert: { contains_any: [\"Ava\"] }\n",
60
+ "'''\n",
61
+ "\n",
62
+ "(repo / \"prompts\" / \"hello_world.prompt.yml\").write_text(prompt_text, encoding=\"utf-8\")\n",
63
+ "print(\"Prompt written:\", repo / \"prompts\" / \"hello_world.prompt.yml\")\n"
64
+ ]
65
+ },
66
+ {
67
+ "cell_type": "code",
68
+ "execution_count": null,
69
+ "id": "33a7f7bd",
70
+ "metadata": {},
71
+ "outputs": [],
72
+ "source": [
73
+ "!ivault validate /content/content/ivault_demo/prompts\n"
74
+ ]
75
+ },
76
+ {
77
+ "cell_type": "code",
78
+ "execution_count": null,
79
+ "id": "040f198b",
80
+ "metadata": {},
81
+ "outputs": [],
82
+ "source": [
83
+ "from instructvault import InstructVault\n",
84
+ "\n",
85
+ "vault = InstructVault(repo_root=\"/content/ivault_demo\")\n",
86
+ "msgs = vault.render(\"prompts/hello_world.prompt.yml\", vars={\"name\":\"Colab\"})\n",
87
+ "print(msgs)\n"
88
+ ]
89
+ },
90
+ {
91
+ "cell_type": "code",
92
+ "execution_count": null,
93
+ "id": "1d6f8472",
94
+ "metadata": {},
95
+ "outputs": [],
96
+ "source": [
97
+ "!ivault eval /ivault_demo/prompts/hello_world.prompt.yml --report /ivault_demo/out/report.json\n"
98
+ ]
99
+ },
100
+ {
101
+ "cell_type": "code",
102
+ "execution_count": null,
103
+ "id": "a5ba9974",
104
+ "metadata": {},
105
+ "outputs": [],
106
+ "source": [
107
+ "!ivault bundle --repo /content/ivault_demo --prompts prompts --out /content/ivault_demo/out/ivault.bundle.json"
108
+ ]
109
+ }
110
+ ],
111
+ "metadata": {
112
+ "colab": {
113
+ "name": "instructvault_colab.ipynb",
114
+ "provenance": []
115
+ },
116
+ "kernelspec": {
117
+ "display_name": "Python 3",
118
+ "language": "python",
119
+ "name": "python3"
120
+ },
121
+ "language_info": {
122
+ "name": "python",
123
+ "version": "3.x"
124
+ }
125
+ },
126
+ "nbformat": 4,
127
+ "nbformat_minor": 5
128
+ }
@@ -0,0 +1,112 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# InstructVault + OpenAI (Google Colab)\n\n",
8
+ "This notebook renders a prompt with InstructVault and sends it to the OpenAI API.\n\n",
9
+ "**Note:** Keep your API key private. Do not commit it to source control."
10
+ ]
11
+ },
12
+ {
13
+ "cell_type": "code",
14
+ "execution_count": null,
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "!pip -q install instructvault openai"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "metadata": {},
25
+ "outputs": [],
26
+ "source": [
27
+ "import os, getpass\n",
28
+ "\n",
29
+ "if 'OPENAI_API_KEY' not in os.environ:\n",
30
+ " os.environ['OPENAI_API_KEY'] = getpass.getpass('Enter OpenAI API key: ')\n",
31
+ "print('API key set:', 'OPENAI_API_KEY' in os.environ)"
32
+ ]
33
+ },
34
+ {
35
+ "cell_type": "code",
36
+ "execution_count": null,
37
+ "metadata": {},
38
+ "outputs": [],
39
+ "source": [
40
+ "from pathlib import Path\n",
41
+ "\n",
42
+ "repo_path = '/content/ivault_demo'\n",
43
+ "repo = Path(repo_path)\n",
44
+ "(repo / 'prompts').mkdir(parents=True, exist_ok=True)\n",
45
+ "\n",
46
+ "prompt_text = '''spec_version: \"1.0\"\n",
47
+ "name: hello_world\n",
48
+ "variables:\n",
49
+ " required: [name]\n",
50
+ "messages:\n",
51
+ " - role: system\n",
52
+ " content: \"You are a helpful assistant.\"\n",
53
+ " - role: user\n",
54
+ " content: \"Say hello to {{ name }}.\"\n",
55
+ "tests:\n",
56
+ " - name: includes_name\n",
57
+ " vars: { name: \"Ava\" }\n",
58
+ " assert: { contains_any: [\"Ava\"] }\n",
59
+ "'''\n",
60
+ "\n",
61
+ "(repo / 'prompts' / 'hello_world.prompt.yml').write_text(prompt_text, encoding='utf-8')\n",
62
+ "print('Prompt written:', repo / 'prompts' / 'hello_world.prompt.yml')"
63
+ ]
64
+ },
65
+ {
66
+ "cell_type": "code",
67
+ "execution_count": null,
68
+ "metadata": {},
69
+ "outputs": [],
70
+ "source": [
71
+ "from instructvault import InstructVault\n",
72
+ "\n",
73
+ "vault = InstructVault(repo_root=repo_path)\n",
74
+ "messages = vault.render('prompts/hello_world.prompt.yml', vars={'name':'Colab'})\n",
75
+ "messages"
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "execution_count": null,
81
+ "metadata": {},
82
+ "outputs": [],
83
+ "source": [
84
+ "from openai import OpenAI\n",
85
+ "\n",
86
+ "client = OpenAI()\n",
87
+ "response = client.chat.completions.create(\n",
88
+ " model='gpt-4.1',\n",
89
+ " messages=messages,\n",
90
+ ")\n",
91
+ "print(response.choices[0].message.content)"
92
+ ]
93
+ }
94
+ ],
95
+ "metadata": {
96
+ "colab": {
97
+ "name": "instructvault_openai_colab.ipynb",
98
+ "provenance": []
99
+ },
100
+ "kernelspec": {
101
+ "display_name": "Python 3",
102
+ "language": "python",
103
+ "name": "python3"
104
+ },
105
+ "language_info": {
106
+ "name": "python",
107
+ "version": "3.x"
108
+ }
109
+ },
110
+ "nbformat": 4,
111
+ "nbformat_minor": 5
112
+ }
@@ -0,0 +1,127 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# InstructVault RAG Cookbook (Google Colab)\n\n",
8
+ "This notebook shows a simple RAG prompt and an agentic RAG prompt using InstructVault."
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "code",
13
+ "execution_count": null,
14
+ "metadata": {},
15
+ "outputs": [],
16
+ "source": [
17
+ "!pip -q install instructvault"
18
+ ]
19
+ },
20
+ {
21
+ "cell_type": "code",
22
+ "execution_count": null,
23
+ "metadata": {},
24
+ "outputs": [],
25
+ "source": [
26
+ "# If you're not on Colab, change this path to your local repo folder.\n",
27
+ "repo_path = \"/content/ivault_demo\"\n",
28
+ "print(\"Using repo_path:\", repo_path)"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "code",
33
+ "execution_count": null,
34
+ "metadata": {},
35
+ "outputs": [],
36
+ "source": [
37
+ "from pathlib import Path\n",
38
+ "\n",
39
+ "repo = Path(repo_path)\n",
40
+ "(repo / \"prompts\").mkdir(parents=True, exist_ok=True)\n",
41
+ "\n",
42
+ "rag_prompt = '''spec_version: \"1.0\"\n",
43
+ "name: rag_answer\n",
44
+ "variables:\n",
45
+ " required: [question, context]\n",
46
+ "messages:\n",
47
+ " - role: system\n",
48
+ " content: \"Answer using only the provided context. If missing, say you don't know.\"\n",
49
+ " - role: user\n",
50
+ " content: \"Question: {{ question }}\\n\\nContext:\\n{{ context }}\"\n",
51
+ "tests:\n",
52
+ " - name: includes_context\n",
53
+ " vars: { question: \"What is InstructVault?\", context: \"InstructVault is a Git-first prompt registry.\" }\n",
54
+ " assert: { contains_any: [\"Context:\"] }\n",
55
+ "'''\n",
56
+ "\n",
57
+ "agent_prompt = '''spec_version: \"1.0\"\n",
58
+ "name: rag_agent\n",
59
+ "variables:\n",
60
+ " required: [question]\n",
61
+ "messages:\n",
62
+ " - role: system\n",
63
+ " content: \"You are a retrieval-augmented agent. Use tools when needed and cite evidence.\"\n",
64
+ " - role: user\n",
65
+ " content: \"Question: {{ question }}\"\n",
66
+ "tests:\n",
67
+ " - name: includes_question\n",
68
+ " vars: { question: \"What is prompt versioning?\" }\n",
69
+ " assert: { contains_any: [\"Question:\"] }\n",
70
+ "'''\n",
71
+ "\n",
72
+ "(repo / \"prompts\" / \"rag_answer.prompt.yml\").write_text(rag_prompt, encoding=\"utf-8\")\n",
73
+ "(repo / \"prompts\" / \"rag_agent.prompt.yml\").write_text(agent_prompt, encoding=\"utf-8\")\n",
74
+ "print(\"Wrote prompts in\", repo / \"prompts\")"
75
+ ]
76
+ },
77
+ {
78
+ "cell_type": "code",
79
+ "execution_count": null,
80
+ "metadata": {},
81
+ "outputs": [],
82
+ "source": [
83
+ "!ivault validate /content/ivault_demo/prompts"
84
+ ]
85
+ },
86
+ {
87
+ "cell_type": "code",
88
+ "execution_count": null,
89
+ "metadata": {},
90
+ "outputs": [],
91
+ "source": [
92
+ "from instructvault import InstructVault\n",
93
+ "\n",
94
+ "vault = InstructVault(repo_root=repo_path)\n",
95
+ "context = \"InstructVault keeps prompts in Git and uses CI for evals.\"\n",
96
+ "msgs = vault.render(\"prompts/rag_answer.prompt.yml\", vars={\"question\": \"What is InstructVault?\", \"context\": context})\n",
97
+ "print(msgs)"
98
+ ]
99
+ },
100
+ {
101
+ "cell_type": "code",
102
+ "execution_count": null,
103
+ "metadata": {},
104
+ "outputs": [],
105
+ "source": [
106
+ "!ivault eval /content/ivault_demo/prompts/rag_answer.prompt.yml --report /content/ivault_demo/out/rag_report.json"
107
+ ]
108
+ }
109
+ ],
110
+ "metadata": {
111
+ "colab": {
112
+ "name": "instructvault_rag_colab.ipynb",
113
+ "provenance": []
114
+ },
115
+ "kernelspec": {
116
+ "display_name": "Python 3",
117
+ "language": "python",
118
+ "name": "python3"
119
+ },
120
+ "language_info": {
121
+ "name": "python",
122
+ "version": "3.x"
123
+ }
124
+ },
125
+ "nbformat": 4,
126
+ "nbformat_minor": 5
127
+ }
@@ -0,0 +1,14 @@
1
+ def check_spec(spec: dict) -> list[str]:
2
+ errors = []
3
+ name = spec.get("name", "")
4
+ if name.startswith("unsafe_"):
5
+ errors.append("prompt name cannot start with 'unsafe_'")
6
+ return errors
7
+
8
+ def check_render(text: str, context: dict) -> list[str]:
9
+ errors = []
10
+ forbidden = ["SSN", "credit card", "password"]
11
+ lowered = text.lower()
12
+ if any(f.lower() in lowered for f in forbidden):
13
+ errors.append("rendered output contains forbidden phrase")
14
+ return errors
@@ -0,0 +1,26 @@
1
+ import re
2
+
3
+ EMAIL = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}")
4
+ SSN = re.compile(r"\\b\\d{3}-\\d{2}-\\d{4}\\b")
5
+ CC = re.compile(r"\\b(?:\\d[ -]*?){13,16}\\b")
6
+
7
+ FORBIDDEN = ["password", "credit card", "ssn"]
8
+
9
+ def check_spec(spec: dict) -> list[str]:
10
+ errors = []
11
+ if spec.get("name", "").startswith("unsafe_"):
12
+ errors.append("prompt name cannot start with 'unsafe_'")
13
+ return errors
14
+
15
+ def check_render(text: str, context: dict) -> list[str]:
16
+ errors = []
17
+ if EMAIL.search(text):
18
+ errors.append("PII detected: email")
19
+ if SSN.search(text):
20
+ errors.append("PII detected: ssn")
21
+ if CC.search(text):
22
+ errors.append("PII detected: credit card")
23
+ lowered = text.lower()
24
+ if any(f in lowered for f in FORBIDDEN):
25
+ errors.append("forbidden phrase detected")
26
+ return errors
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "instructvault"
3
- version = "0.2.8"
3
+ version = "0.3.0"
4
4
  description = "Git-first prompt registry + CI evals + lightweight runtime SDK (ivault)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -12,6 +12,7 @@ dependencies = [
12
12
  "pyyaml>=6.0",
13
13
  "jinja2>=3.1",
14
14
  "rich>=13.7",
15
+ "jsonschema>=4.21",
15
16
  ]
16
17
 
17
18
  [project.optional-dependencies]