prompt-optimizer-tool 0.1.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_optimizer_tool-0.1.0/LICENSE +21 -0
- prompt_optimizer_tool-0.1.0/PKG-INFO +298 -0
- prompt_optimizer_tool-0.1.0/README.md +274 -0
- prompt_optimizer_tool-0.1.0/pyproject.toml +47 -0
- prompt_optimizer_tool-0.1.0/setup.cfg +4 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/__init__.py +17 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/analyzer.py +39 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/cli.py +287 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/config.py +85 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/llm.py +61 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/optimizer.py +44 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/principles.py +172 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/schemas.py +56 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool/storage.py +58 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool.egg-info/PKG-INFO +298 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool.egg-info/SOURCES.txt +24 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool.egg-info/dependency_links.txt +1 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool.egg-info/entry_points.txt +2 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool.egg-info/requires.txt +6 -0
- prompt_optimizer_tool-0.1.0/src/prompt_optimizer_tool.egg-info/top_level.txt +1 -0
- prompt_optimizer_tool-0.1.0/tests/test_cli.py +147 -0
- prompt_optimizer_tool-0.1.0/tests/test_config.py +49 -0
- prompt_optimizer_tool-0.1.0/tests/test_pipeline.py +116 -0
- prompt_optimizer_tool-0.1.0/tests/test_principles.py +38 -0
- prompt_optimizer_tool-0.1.0/tests/test_schemas.py +49 -0
- prompt_optimizer_tool-0.1.0/tests/test_storage.py +45 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 khadar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prompt-optimizer-tool
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI tool that grades prompts 0-100 against 10 engineering principles and rewrites them, powered by Groq
|
|
5
|
+
Author-email: khadar <khadarbashajilan001@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/khadarbashajilan/prompt-optimizer-tool
|
|
8
|
+
Project-URL: Issues, https://github.com/khadarbashajilan/prompt-optimizer-tool/issues
|
|
9
|
+
Keywords: prompt,prompt-engineering,llm,groq,langchain,cli
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
|
+
Classifier: Topic :: Software Development
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: langchain-groq>=1.1.0
|
|
18
|
+
Requires-Dist: langchain-core>=0.3.0
|
|
19
|
+
Requires-Dist: rich>=13.0.0
|
|
20
|
+
Requires-Dist: click>=8.0.0
|
|
21
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# Prompt Optimizer
|
|
26
|
+
|
|
27
|
+
A CLI tool that **analyzes and rewrites prompts** following established prompt engineering best practices. Powered by **LangChain** + **Groq** (free tier, no credit card).
|
|
28
|
+
|
|
29
|
+
## Why I Built This
|
|
30
|
+
|
|
31
|
+
Prompt engineering is no longer about trial and error — it's a discipline with repeatable patterns (role definition, output contracts, chain-of-thought, constraints). Most developers still write vague, unstructured prompts that leave LLMs guessing. This tool automates the optimization cycle:
|
|
32
|
+
|
|
33
|
+
1. **Analyze** — identify exactly what's wrong with a prompt against 10 principles
|
|
34
|
+
2. **Structure** — rewrite it with role, objective, context, step-by-step instructions, constraints, and output format
|
|
35
|
+
3. **Iterate** — test the optimized prompt, refine, and repeat
|
|
36
|
+
|
|
37
|
+
The goal is to make production-quality prompting accessible from the terminal.
|
|
38
|
+
|
|
39
|
+
## Architecture
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
┌──────────────┐
|
|
43
|
+
│ principles │ 10 rules + both system prompts
|
|
44
|
+
│ .py │ (generated from one table)
|
|
45
|
+
└──────┬───────┘
|
|
46
|
+
│
|
|
47
|
+
┌───────────┐ ┌───────┴────────┐ ┌────────────┐ ┌──────────┐
|
|
48
|
+
│ cli.py │──▶│ analyzer.py │──▶│ llm.py │──▶│ Groq │
|
|
49
|
+
│ Click+Rich│ │ optimizer.py │ │ ChatGroq + │ │ API │
|
|
50
|
+
└─────┬─────┘ └───────┬────────┘ │ structured │ └──────────┘
|
|
51
|
+
│ │ │ output │
|
|
52
|
+
│ ┌────┴─────┐ └─────┬──────┘
|
|
53
|
+
│ │ schemas │ │
|
|
54
|
+
│ │ .py │ ┌─────┴──────┐
|
|
55
|
+
│ │ Pydantic │ │ config.py │
|
|
56
|
+
│ └──────────┘ │ settings │
|
|
57
|
+
│ │ + API key│
|
|
58
|
+
▼ └────────────┘
|
|
59
|
+
┌──────────┐
|
|
60
|
+
│ storage │ one timestamped file per run, into saved/
|
|
61
|
+
│ .py │
|
|
62
|
+
└──────────┘
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| Module | Role |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `cli.py` | Click entry point, Rich rendering, input gathering (arg / `--file` / stdin) |
|
|
68
|
+
| `analyzer.py` | Step 1 — prompt + grading instructions → `PromptAnalysis` |
|
|
69
|
+
| `optimizer.py` | Step 2 — prompt + analysis + rewrite instructions → `OptimizedPrompt` |
|
|
70
|
+
| `principles.py` | The 10 rules as one table; both system prompts are generated from it |
|
|
71
|
+
| `schemas.py` | Pydantic contracts: `PromptWeakness`, `PromptAnalysis`, `OptimizedPrompt` |
|
|
72
|
+
| `llm.py` | The only module that knows how to talk to Groq |
|
|
73
|
+
| `config.py` | Every setting in one place, each overridable by env var |
|
|
74
|
+
| `storage.py` | Builds a timestamped path per run and writes it |
|
|
75
|
+
| `run.sh` | Bootstraps the venv, checks the API key, then offers an interactive menu |
|
|
76
|
+
|
|
77
|
+
Dependencies point one way only: `cli` → `analyzer`/`optimizer` → `llm` → `config`.
|
|
78
|
+
`principles` and `schemas` sit at the bottom with no internal dependencies, so
|
|
79
|
+
either step can be swapped, retried, or tested without touching the other.
|
|
80
|
+
|
|
81
|
+
### Workflow
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
User Prompt ──▶ Analyze ──▶ Quality Score (0-100)
|
|
85
|
+
│ + Strengths
|
|
86
|
+
│ + Weaknesses (with severity & suggestions)
|
|
87
|
+
▼
|
|
88
|
+
Optimize ──▶ Structured Prompt
|
|
89
|
+
+ Role / Objective / Context
|
|
90
|
+
+ Step-by-Step Instructions
|
|
91
|
+
+ Constraints & Rules
|
|
92
|
+
+ Output Format
|
|
93
|
+
+ Success Criteria
|
|
94
|
+
+ Changes Made Summary
|
|
95
|
+
+ Principles Applied List
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### The 10 Principles
|
|
99
|
+
|
|
100
|
+
Defined once in `principles.py` and reused everywhere:
|
|
101
|
+
|
|
102
|
+
1. **Role & Persona Definition** — assign expertise level and perspective
|
|
103
|
+
2. **Clear Objective** — one-sentence goal statement
|
|
104
|
+
3. **Context Provision** — background, audience, environment
|
|
105
|
+
4. **Step-by-Step Instructions** — sequential breakdown of complex tasks
|
|
106
|
+
5. **Constraints & Rules** — boundaries, exclusions, length limits
|
|
107
|
+
6. **Output Format Specification** — JSON, markdown, bullet points, etc.
|
|
108
|
+
7. **Few-Shot Examples** — demonstrate desired pattern with examples
|
|
109
|
+
8. **Chain of Thought** — request reasoning for multi-step problems
|
|
110
|
+
9. **Success Criteria** — define measurable quality bar
|
|
111
|
+
10. **Specific Language** — replace vague qualifiers with precise terms
|
|
112
|
+
|
|
113
|
+
## Tech Stack
|
|
114
|
+
|
|
115
|
+
| Technology | Where Used | Purpose |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| **Groq** (`openai/gpt-oss-20b`) | `src/llm.py:35` | Powers both LLM calls via `ChatGroq`. Free tier, no credit card required |
|
|
118
|
+
| **LangChain** (`ChatGroq`, `ChatPromptTemplate`) | `src/llm.py:61`, `src/analyzer.py:30`, `src/optimizer.py:31` | Provider abstraction, prompt templates, chain composition with LCEL |
|
|
119
|
+
| **Structured Outputs** (`with_structured_output`) | `src/llm.py:61` | Groq's `json_schema` mode in **strict** mode uses constrained decoding, so every response matches the Pydantic schema — no JSON parse errors, and `Literal` fields can only return declared values |
|
|
120
|
+
| **Pydantic v2** (`BaseModel`, `Field`) | `schemas.py:19-56` | Data contracts for `PromptWeakness`, `PromptAnalysis`, `OptimizedPrompt` — validation + serialization |
|
|
121
|
+
| **Click** (`@click.group`, `@click.command`, `@click.option`) | `src/cli.py:233-270` | CLI framework with composable commands, argument parsing, and auto-generated `--help` |
|
|
122
|
+
| **Rich** (`Console`, `Panel`, `Table`, `Markdown`, `Columns`) | `src/cli.py:53-137` | Terminal UI — color-coded score panels, weakness tables, markdown rendering, status spinners |
|
|
123
|
+
| **python-dotenv** (`load_dotenv`) | `src/config.py:15` | Auto-loads `GROQ_API_KEY` from `.env` file — no manual config flags |
|
|
124
|
+
| **pytest** (offline suite) | `tests/` | ~43 cases, no API key or network needed: CLI flow via `CliRunner`, the LLM seam with a fake provider, schemas, principles, config, storage |
|
|
125
|
+
| **uv** | `pyproject.toml` | Package manager — single `uv sync` installs deps, builds package, registers CLI entry point |
|
|
126
|
+
| **Python 3.12** | `.python-version`, `pyproject.toml` | Type hints (`list[str]`, `dict[str, str]`), `str.removeprefix`/`removesuffix` |
|
|
127
|
+
|
|
128
|
+
## Installation
|
|
129
|
+
|
|
130
|
+
Published on PyPI as [`prompt-optimizer-tool`](https://pypi.org/project/prompt-optimizer-tool/).
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Try it instantly, nothing is installed
|
|
134
|
+
uvx --from prompt-optimizer-tool prompt-optimizer list
|
|
135
|
+
|
|
136
|
+
# Install as an isolated tool (recommended)
|
|
137
|
+
uv tool install prompt-optimizer-tool
|
|
138
|
+
|
|
139
|
+
# or with pipx
|
|
140
|
+
pipx install prompt-optimizer-tool
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Set your Groq API key (free, no credit card: https://console.groq.com/keys)
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
export GROQ_API_KEY=gsk_your-key-here
|
|
147
|
+
prompt-optimizer optimize "write code in python to fetch api data"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Install from source (alternative)
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git clone https://github.com/khadarbashajilan/prompt-optimizer-tool.git
|
|
154
|
+
cd prompt-optimizer-tool
|
|
155
|
+
cp .env.example .env # then edit .env: GROQ_API_KEY=gsk_your-key-here
|
|
156
|
+
./run.sh
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Quick start
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Interactive menu — the easiest way in
|
|
163
|
+
./run.sh
|
|
164
|
+
|
|
165
|
+
# Or pass arguments straight through to the CLI
|
|
166
|
+
./run.sh optimize "write code in python to fetch api data"
|
|
167
|
+
./run.sh optimize --file prompt.txt
|
|
168
|
+
./run.sh list
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`./run.sh` with no arguments opens a menu: optimize a pasted prompt, optimize
|
|
172
|
+
a file, list the 10 principles, show help, or quit. It verifies
|
|
173
|
+
`GROQ_API_KEY` is set and creates the virtualenv on first run.
|
|
174
|
+
|
|
175
|
+
## Usage
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Basic — analyze + optimize a prompt
|
|
179
|
+
uv run prompt-optimizer optimize "write code in python to fetch api data"
|
|
180
|
+
|
|
181
|
+
# Read from file
|
|
182
|
+
uv run prompt-optimizer optimize --file prompt.txt
|
|
183
|
+
|
|
184
|
+
# Pipe from stdin
|
|
185
|
+
echo "explain quantum computing to a 5 year old" | uv run prompt-optimizer optimize
|
|
186
|
+
|
|
187
|
+
# Each run is auto-saved to its own timestamped file in saved/
|
|
188
|
+
uv run prompt-optimizer optimize "write a blog post"
|
|
189
|
+
# → saved/optimized-20260927-143205.md
|
|
190
|
+
|
|
191
|
+
# Choose a different output folder
|
|
192
|
+
uv run prompt-optimizer optimize "write a blog post" --out ~/prompts
|
|
193
|
+
|
|
194
|
+
# List all 10 prompting principles
|
|
195
|
+
uv run prompt-optimizer list
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Configuration
|
|
199
|
+
|
|
200
|
+
Every setting has a default and can be overridden with an environment
|
|
201
|
+
variable, so none of them require a code change:
|
|
202
|
+
|
|
203
|
+
| Variable | Default | Means |
|
|
204
|
+
|---|---|---|
|
|
205
|
+
| `GROQ_API_KEY` | *(required)* | Authorises the calls. Read from `.env` |
|
|
206
|
+
| `PROMPT_OPTIMIZER_MODEL` | `openai/gpt-oss-20b` | Which Groq model to use |
|
|
207
|
+
| `PROMPT_OPTIMIZER_TEMPERATURE` | `0.6` | Higher means more varied wording |
|
|
208
|
+
| `PROMPT_OPTIMIZER_MAX_TOKENS` | `4096` | Reply ceiling; lower values truncate long rewrites |
|
|
209
|
+
| `PROMPT_OPTIMIZER_MAX_RETRIES` | `3` | Attempts per call, handles free-tier rate limits |
|
|
210
|
+
| `PROMPT_OPTIMIZER_TIMEOUT` | `60` | Per-request seconds, so a stalled call cannot hang |
|
|
211
|
+
| `PROMPT_OPTIMIZER_OUTPUT_DIR` | `saved` | Default folder for saved rewrites |
|
|
212
|
+
|
|
213
|
+
### Example Output
|
|
214
|
+
|
|
215
|
+
The tool produces a structured report:
|
|
216
|
+
|
|
217
|
+
- **Quality Score** — color-coded (green ≥70, yellow ≥40, red <40)
|
|
218
|
+
- **Strengths** — what the original prompt does well
|
|
219
|
+
- **Weaknesses & Improvements** — each issue with severity, violated principle, and concrete fix
|
|
220
|
+
- **Changes Made** — summary of all improvements applied
|
|
221
|
+
- **Optimized Prompt** — the complete rewritten prompt (copy-ready)
|
|
222
|
+
- **Principles Applied** — which of the 10 principles were used
|
|
223
|
+
- **Auto-save** — every run writes its own file to `saved/`, named for the date and time of the run, so results accumulate instead of overwriting
|
|
224
|
+
|
|
225
|
+
## Limitations and Roadmap
|
|
226
|
+
|
|
227
|
+
What this tool does **not** do yet, so expectations are clear:
|
|
228
|
+
|
|
229
|
+
| Limitation | Current behavior | Fix |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| **No logging** | Errors print to the terminal only; no debug trail | Add structured logging (log file + `--debug` flag) |
|
|
232
|
+
| **No caching** | Analyze + Optimize each hit the API on every run | Cache analyses by prompt hash to avoid repeat cost |
|
|
233
|
+
| **No live-model tests** | The ~43 offline tests fake the provider seam only; real Groq structured-output calls are verified by hand | Add an opt-in integration test with a real key |
|
|
234
|
+
| **No model fallback** | If the configured model is unavailable the run fails after retries | Add a second model to fall back to |
|
|
235
|
+
| **Console only** | No way to diff a rewrite against its previous version | Add `--diff <file>` to compare two saved runs |
|
|
236
|
+
| **No CI** | Checks only run locally | Add a GitHub Actions workflow |
|
|
237
|
+
|
|
238
|
+
Planned next: logging, and an opt-in live-model integration test.
|
|
239
|
+
|
|
240
|
+
## Key Design Decisions
|
|
241
|
+
|
|
242
|
+
- **Structured Outputs in strict mode** — using `with_structured_output(Model, method="json_schema", strict=True)`. Groq's strict mode uses constrained decoding, so the response is guaranteed to match the Pydantic schema. Tool calling would be the alternative, but Groq does not support tool use together with Structured Outputs, and strict mode is the stronger guarantee.
|
|
243
|
+
- **Constrained decoding doubles as validation** — because the decoder can only emit declared values, `Literal` fields (`severity`, `principle`, `principles_applied`) cannot come back as typos or invented names. This is what guarantees the "Principles Applied" panel can always resolve a principle, instead of silently rendering nothing when the model returns a name rather than a key.
|
|
244
|
+
- **Closed schemas only** — strict mode requires every field to be required and every object to set `additionalProperties: false`. A free-form `dict[str, str]` collapses to an always-empty object under those rules, so `sections` is a `list[PromptSection]` (explicit `name` + `content`) instead.
|
|
245
|
+
- **Model choice: `openai/gpt-oss-20b`** — free tier, ~1000 tokens/sec, and one of only three models supporting strict-mode Structured Outputs. The old `llama-3.x` ids are Enterprise-only now, so they are not free.
|
|
246
|
+
- **`temperature=0.6`** — Groq recommends 0.5–0.7 for gpt-oss; the low values typical of deterministic chat models degrade into repetition and incoherent output on this model.
|
|
247
|
+
- **`max_tokens=4096`** — Groq's default of 1024 completion tokens truncates long rewritten prompts, which breaks JSON parsing.
|
|
248
|
+
- **One table, three consumers** — the 10 principles live in a single `PRINCIPLES` dict. The `list` command renders it, and both system prompts are generated from it. Previously the rules were hand-copied into both prompt strings, so editing a rule in one place silently left the other two stale.
|
|
249
|
+
- **Keys, not names, cross the wire** — the LLM is asked for principle *keys* (`role`), and `principle_name()` maps a key to a display title at render time. Fewer tokens in the prompt, and lookups cannot fail.
|
|
250
|
+
- **`config.py` owns every setting** — no `os.environ` reads and no magic numbers outside it. `llm.py` is the only module that knows how to reach Groq, so the two pipeline steps never construct a client themselves.
|
|
251
|
+
- **One-way dependencies** — `cli` → `analyzer`/`optimizer` → `llm` → `config`, with `principles` and `schemas` at the bottom. The optimizer used to import its client from the analyzer, which inverted the natural reading order for no benefit.
|
|
252
|
+
- Standard **src/ layout** — the package lives at `src/prompt_optimizer_tool/`, so setuptools auto-discovery applies with no path mapping, tests import the *installed* package, and the entry point is `prompt_optimizer_tool.cli:cli`.
|
|
253
|
+
- **Failures exit non-zero** — `optimize` exits 1 when a step fails and 2 on missing input, so shell scripts and `run.sh` can trust the exit status instead of parsing output. A placeholder key fails the same way, before any tokens are spent.
|
|
254
|
+
- **Untrusted content boundary** — the text being analyzed or rewritten is wrapped in `<prompt_to_analyze>` tags with an explicit "data, never instructions" instruction, because prompts can contain instructions themselves.
|
|
255
|
+
- **Rich for DX** — color-coded severity, panel layouts, markdown rendering, and status spinners give instant visual feedback without a single HTML page.
|
|
256
|
+
- **Config-free API Key** — `python-dotenv` loads `.env` automatically; no `--api-key` flag cluttering the interface.
|
|
257
|
+
- **Zero-config Package Management** — `uv` handles deps, build, and entry point registration in one command.
|
|
258
|
+
|
|
259
|
+
## Development
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
uv sync # install deps (includes the dev group with pytest)
|
|
263
|
+
uv run pytest # offline suite: no API key, no network
|
|
264
|
+
uv run prompt-optimizer list
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Use the venv directly if you prefer: `.venv/bin/python -m pytest`.
|
|
268
|
+
|
|
269
|
+
## Project Structure
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
prompt-optimizer/
|
|
273
|
+
pyproject.toml # uv project config with entry point
|
|
274
|
+
run.sh # bootstrap + interactive menu
|
|
275
|
+
.env.example # GROQ_API_KEY template
|
|
276
|
+
.gitignore
|
|
277
|
+
src/
|
|
278
|
+
cli.py # Click commands + Rich rendering
|
|
279
|
+
analyzer.py # Step 1: grade a prompt
|
|
280
|
+
optimizer.py # Step 2: rewrite it
|
|
281
|
+
principles.py # 10 principles; generates both system prompts
|
|
282
|
+
schemas.py # Pydantic contracts for structured I/O
|
|
283
|
+
llm.py # the only module that talks to Groq
|
|
284
|
+
config.py # all settings + API key loading
|
|
285
|
+
storage.py # timestamped path per run, then write
|
|
286
|
+
tests/
|
|
287
|
+
support.py # FakeProvider + fresh-model factories
|
|
288
|
+
conftest.py # fixtures for the two test seams
|
|
289
|
+
test_cli.py # end-to-end: input modes, exit codes, saving
|
|
290
|
+
test_pipeline.py # schema + message contracts at the LLM seam
|
|
291
|
+
test_principles.py # table/Literal/prompt consistency
|
|
292
|
+
test_schemas.py # validation bounds and Literal values
|
|
293
|
+
test_config.py # API key resolution + placeholder rejection
|
|
294
|
+
test_storage.py # timestamped naming, collision, folders
|
|
295
|
+
saved/ # one file per run, gitignored
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Prompt Optimizer
|
|
2
|
+
|
|
3
|
+
A CLI tool that **analyzes and rewrites prompts** following established prompt engineering best practices. Powered by **LangChain** + **Groq** (free tier, no credit card).
|
|
4
|
+
|
|
5
|
+
## Why I Built This
|
|
6
|
+
|
|
7
|
+
Prompt engineering is no longer about trial and error — it's a discipline with repeatable patterns (role definition, output contracts, chain-of-thought, constraints). Most developers still write vague, unstructured prompts that leave LLMs guessing. This tool automates the optimization cycle:
|
|
8
|
+
|
|
9
|
+
1. **Analyze** — identify exactly what's wrong with a prompt against 10 principles
|
|
10
|
+
2. **Structure** — rewrite it with role, objective, context, step-by-step instructions, constraints, and output format
|
|
11
|
+
3. **Iterate** — test the optimized prompt, refine, and repeat
|
|
12
|
+
|
|
13
|
+
The goal is to make production-quality prompting accessible from the terminal.
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
┌──────────────┐
|
|
19
|
+
│ principles │ 10 rules + both system prompts
|
|
20
|
+
│ .py │ (generated from one table)
|
|
21
|
+
└──────┬───────┘
|
|
22
|
+
│
|
|
23
|
+
┌───────────┐ ┌───────┴────────┐ ┌────────────┐ ┌──────────┐
|
|
24
|
+
│ cli.py │──▶│ analyzer.py │──▶│ llm.py │──▶│ Groq │
|
|
25
|
+
│ Click+Rich│ │ optimizer.py │ │ ChatGroq + │ │ API │
|
|
26
|
+
└─────┬─────┘ └───────┬────────┘ │ structured │ └──────────┘
|
|
27
|
+
│ │ │ output │
|
|
28
|
+
│ ┌────┴─────┐ └─────┬──────┘
|
|
29
|
+
│ │ schemas │ │
|
|
30
|
+
│ │ .py │ ┌─────┴──────┐
|
|
31
|
+
│ │ Pydantic │ │ config.py │
|
|
32
|
+
│ └──────────┘ │ settings │
|
|
33
|
+
│ │ + API key│
|
|
34
|
+
▼ └────────────┘
|
|
35
|
+
┌──────────┐
|
|
36
|
+
│ storage │ one timestamped file per run, into saved/
|
|
37
|
+
│ .py │
|
|
38
|
+
└──────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Module | Role |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `cli.py` | Click entry point, Rich rendering, input gathering (arg / `--file` / stdin) |
|
|
44
|
+
| `analyzer.py` | Step 1 — prompt + grading instructions → `PromptAnalysis` |
|
|
45
|
+
| `optimizer.py` | Step 2 — prompt + analysis + rewrite instructions → `OptimizedPrompt` |
|
|
46
|
+
| `principles.py` | The 10 rules as one table; both system prompts are generated from it |
|
|
47
|
+
| `schemas.py` | Pydantic contracts: `PromptWeakness`, `PromptAnalysis`, `OptimizedPrompt` |
|
|
48
|
+
| `llm.py` | The only module that knows how to talk to Groq |
|
|
49
|
+
| `config.py` | Every setting in one place, each overridable by env var |
|
|
50
|
+
| `storage.py` | Builds a timestamped path per run and writes it |
|
|
51
|
+
| `run.sh` | Bootstraps the venv, checks the API key, then offers an interactive menu |
|
|
52
|
+
|
|
53
|
+
Dependencies point one way only: `cli` → `analyzer`/`optimizer` → `llm` → `config`.
|
|
54
|
+
`principles` and `schemas` sit at the bottom with no internal dependencies, so
|
|
55
|
+
either step can be swapped, retried, or tested without touching the other.
|
|
56
|
+
|
|
57
|
+
### Workflow
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
User Prompt ──▶ Analyze ──▶ Quality Score (0-100)
|
|
61
|
+
│ + Strengths
|
|
62
|
+
│ + Weaknesses (with severity & suggestions)
|
|
63
|
+
▼
|
|
64
|
+
Optimize ──▶ Structured Prompt
|
|
65
|
+
+ Role / Objective / Context
|
|
66
|
+
+ Step-by-Step Instructions
|
|
67
|
+
+ Constraints & Rules
|
|
68
|
+
+ Output Format
|
|
69
|
+
+ Success Criteria
|
|
70
|
+
+ Changes Made Summary
|
|
71
|
+
+ Principles Applied List
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### The 10 Principles
|
|
75
|
+
|
|
76
|
+
Defined once in `principles.py` and reused everywhere:
|
|
77
|
+
|
|
78
|
+
1. **Role & Persona Definition** — assign expertise level and perspective
|
|
79
|
+
2. **Clear Objective** — one-sentence goal statement
|
|
80
|
+
3. **Context Provision** — background, audience, environment
|
|
81
|
+
4. **Step-by-Step Instructions** — sequential breakdown of complex tasks
|
|
82
|
+
5. **Constraints & Rules** — boundaries, exclusions, length limits
|
|
83
|
+
6. **Output Format Specification** — JSON, markdown, bullet points, etc.
|
|
84
|
+
7. **Few-Shot Examples** — demonstrate desired pattern with examples
|
|
85
|
+
8. **Chain of Thought** — request reasoning for multi-step problems
|
|
86
|
+
9. **Success Criteria** — define measurable quality bar
|
|
87
|
+
10. **Specific Language** — replace vague qualifiers with precise terms
|
|
88
|
+
|
|
89
|
+
## Tech Stack
|
|
90
|
+
|
|
91
|
+
| Technology | Where Used | Purpose |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| **Groq** (`openai/gpt-oss-20b`) | `src/llm.py:35` | Powers both LLM calls via `ChatGroq`. Free tier, no credit card required |
|
|
94
|
+
| **LangChain** (`ChatGroq`, `ChatPromptTemplate`) | `src/llm.py:61`, `src/analyzer.py:30`, `src/optimizer.py:31` | Provider abstraction, prompt templates, chain composition with LCEL |
|
|
95
|
+
| **Structured Outputs** (`with_structured_output`) | `src/llm.py:61` | Groq's `json_schema` mode in **strict** mode uses constrained decoding, so every response matches the Pydantic schema — no JSON parse errors, and `Literal` fields can only return declared values |
|
|
96
|
+
| **Pydantic v2** (`BaseModel`, `Field`) | `schemas.py:19-56` | Data contracts for `PromptWeakness`, `PromptAnalysis`, `OptimizedPrompt` — validation + serialization |
|
|
97
|
+
| **Click** (`@click.group`, `@click.command`, `@click.option`) | `src/cli.py:233-270` | CLI framework with composable commands, argument parsing, and auto-generated `--help` |
|
|
98
|
+
| **Rich** (`Console`, `Panel`, `Table`, `Markdown`, `Columns`) | `src/cli.py:53-137` | Terminal UI — color-coded score panels, weakness tables, markdown rendering, status spinners |
|
|
99
|
+
| **python-dotenv** (`load_dotenv`) | `src/config.py:15` | Auto-loads `GROQ_API_KEY` from `.env` file — no manual config flags |
|
|
100
|
+
| **pytest** (offline suite) | `tests/` | ~43 cases, no API key or network needed: CLI flow via `CliRunner`, the LLM seam with a fake provider, schemas, principles, config, storage |
|
|
101
|
+
| **uv** | `pyproject.toml` | Package manager — single `uv sync` installs deps, builds package, registers CLI entry point |
|
|
102
|
+
| **Python 3.12** | `.python-version`, `pyproject.toml` | Type hints (`list[str]`, `dict[str, str]`), `str.removeprefix`/`removesuffix` |
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
Published on PyPI as [`prompt-optimizer-tool`](https://pypi.org/project/prompt-optimizer-tool/).
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Try it instantly, nothing is installed
|
|
110
|
+
uvx --from prompt-optimizer-tool prompt-optimizer list
|
|
111
|
+
|
|
112
|
+
# Install as an isolated tool (recommended)
|
|
113
|
+
uv tool install prompt-optimizer-tool
|
|
114
|
+
|
|
115
|
+
# or with pipx
|
|
116
|
+
pipx install prompt-optimizer-tool
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Set your Groq API key (free, no credit card: https://console.groq.com/keys)
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
export GROQ_API_KEY=gsk_your-key-here
|
|
123
|
+
prompt-optimizer optimize "write code in python to fetch api data"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Install from source (alternative)
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
git clone https://github.com/khadarbashajilan/prompt-optimizer-tool.git
|
|
130
|
+
cd prompt-optimizer-tool
|
|
131
|
+
cp .env.example .env # then edit .env: GROQ_API_KEY=gsk_your-key-here
|
|
132
|
+
./run.sh
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Quick start
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Interactive menu — the easiest way in
|
|
139
|
+
./run.sh
|
|
140
|
+
|
|
141
|
+
# Or pass arguments straight through to the CLI
|
|
142
|
+
./run.sh optimize "write code in python to fetch api data"
|
|
143
|
+
./run.sh optimize --file prompt.txt
|
|
144
|
+
./run.sh list
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`./run.sh` with no arguments opens a menu: optimize a pasted prompt, optimize
|
|
148
|
+
a file, list the 10 principles, show help, or quit. It verifies
|
|
149
|
+
`GROQ_API_KEY` is set and creates the virtualenv on first run.
|
|
150
|
+
|
|
151
|
+
## Usage
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Basic — analyze + optimize a prompt
|
|
155
|
+
uv run prompt-optimizer optimize "write code in python to fetch api data"
|
|
156
|
+
|
|
157
|
+
# Read from file
|
|
158
|
+
uv run prompt-optimizer optimize --file prompt.txt
|
|
159
|
+
|
|
160
|
+
# Pipe from stdin
|
|
161
|
+
echo "explain quantum computing to a 5 year old" | uv run prompt-optimizer optimize
|
|
162
|
+
|
|
163
|
+
# Each run is auto-saved to its own timestamped file in saved/
|
|
164
|
+
uv run prompt-optimizer optimize "write a blog post"
|
|
165
|
+
# → saved/optimized-20260927-143205.md
|
|
166
|
+
|
|
167
|
+
# Choose a different output folder
|
|
168
|
+
uv run prompt-optimizer optimize "write a blog post" --out ~/prompts
|
|
169
|
+
|
|
170
|
+
# List all 10 prompting principles
|
|
171
|
+
uv run prompt-optimizer list
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Configuration
|
|
175
|
+
|
|
176
|
+
Every setting has a default and can be overridden with an environment
|
|
177
|
+
variable, so none of them require a code change:
|
|
178
|
+
|
|
179
|
+
| Variable | Default | Means |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| `GROQ_API_KEY` | *(required)* | Authorises the calls. Read from `.env` |
|
|
182
|
+
| `PROMPT_OPTIMIZER_MODEL` | `openai/gpt-oss-20b` | Which Groq model to use |
|
|
183
|
+
| `PROMPT_OPTIMIZER_TEMPERATURE` | `0.6` | Higher means more varied wording |
|
|
184
|
+
| `PROMPT_OPTIMIZER_MAX_TOKENS` | `4096` | Reply ceiling; lower values truncate long rewrites |
|
|
185
|
+
| `PROMPT_OPTIMIZER_MAX_RETRIES` | `3` | Attempts per call, handles free-tier rate limits |
|
|
186
|
+
| `PROMPT_OPTIMIZER_TIMEOUT` | `60` | Per-request seconds, so a stalled call cannot hang |
|
|
187
|
+
| `PROMPT_OPTIMIZER_OUTPUT_DIR` | `saved` | Default folder for saved rewrites |
|
|
188
|
+
|
|
189
|
+
### Example Output
|
|
190
|
+
|
|
191
|
+
The tool produces a structured report:
|
|
192
|
+
|
|
193
|
+
- **Quality Score** — color-coded (green ≥70, yellow ≥40, red <40)
|
|
194
|
+
- **Strengths** — what the original prompt does well
|
|
195
|
+
- **Weaknesses & Improvements** — each issue with severity, violated principle, and concrete fix
|
|
196
|
+
- **Changes Made** — summary of all improvements applied
|
|
197
|
+
- **Optimized Prompt** — the complete rewritten prompt (copy-ready)
|
|
198
|
+
- **Principles Applied** — which of the 10 principles were used
|
|
199
|
+
- **Auto-save** — every run writes its own file to `saved/`, named for the date and time of the run, so results accumulate instead of overwriting
|
|
200
|
+
|
|
201
|
+
## Limitations and Roadmap
|
|
202
|
+
|
|
203
|
+
What this tool does **not** do yet, so expectations are clear:
|
|
204
|
+
|
|
205
|
+
| Limitation | Current behavior | Fix |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| **No logging** | Errors print to the terminal only; no debug trail | Add structured logging (log file + `--debug` flag) |
|
|
208
|
+
| **No caching** | Analyze + Optimize each hit the API on every run | Cache analyses by prompt hash to avoid repeat cost |
|
|
209
|
+
| **No live-model tests** | The ~43 offline tests fake the provider seam only; real Groq structured-output calls are verified by hand | Add an opt-in integration test with a real key |
|
|
210
|
+
| **No model fallback** | If the configured model is unavailable the run fails after retries | Add a second model to fall back to |
|
|
211
|
+
| **Console only** | No way to diff a rewrite against its previous version | Add `--diff <file>` to compare two saved runs |
|
|
212
|
+
| **No CI** | Checks only run locally | Add a GitHub Actions workflow |
|
|
213
|
+
|
|
214
|
+
Planned next: logging, and an opt-in live-model integration test.
|
|
215
|
+
|
|
216
|
+
## Key Design Decisions
|
|
217
|
+
|
|
218
|
+
- **Structured Outputs in strict mode** — using `with_structured_output(Model, method="json_schema", strict=True)`. Groq's strict mode uses constrained decoding, so the response is guaranteed to match the Pydantic schema. Tool calling would be the alternative, but Groq does not support tool use together with Structured Outputs, and strict mode is the stronger guarantee.
|
|
219
|
+
- **Constrained decoding doubles as validation** — because the decoder can only emit declared values, `Literal` fields (`severity`, `principle`, `principles_applied`) cannot come back as typos or invented names. This is what guarantees the "Principles Applied" panel can always resolve a principle, instead of silently rendering nothing when the model returns a name rather than a key.
|
|
220
|
+
- **Closed schemas only** — strict mode requires every field to be required and every object to set `additionalProperties: false`. A free-form `dict[str, str]` collapses to an always-empty object under those rules, so `sections` is a `list[PromptSection]` (explicit `name` + `content`) instead.
|
|
221
|
+
- **Model choice: `openai/gpt-oss-20b`** — free tier, ~1000 tokens/sec, and one of only three models supporting strict-mode Structured Outputs. The old `llama-3.x` ids are Enterprise-only now, so they are not free.
|
|
222
|
+
- **`temperature=0.6`** — Groq recommends 0.5–0.7 for gpt-oss; the low values typical of deterministic chat models degrade into repetition and incoherent output on this model.
|
|
223
|
+
- **`max_tokens=4096`** — Groq's default of 1024 completion tokens truncates long rewritten prompts, which breaks JSON parsing.
|
|
224
|
+
- **One table, three consumers** — the 10 principles live in a single `PRINCIPLES` dict. The `list` command renders it, and both system prompts are generated from it. Previously the rules were hand-copied into both prompt strings, so editing a rule in one place silently left the other two stale.
|
|
225
|
+
- **Keys, not names, cross the wire** — the LLM is asked for principle *keys* (`role`), and `principle_name()` maps a key to a display title at render time. Fewer tokens in the prompt, and lookups cannot fail.
|
|
226
|
+
- **`config.py` owns every setting** — no `os.environ` reads and no magic numbers outside it. `llm.py` is the only module that knows how to reach Groq, so the two pipeline steps never construct a client themselves.
|
|
227
|
+
- **One-way dependencies** — `cli` → `analyzer`/`optimizer` → `llm` → `config`, with `principles` and `schemas` at the bottom. The optimizer used to import its client from the analyzer, which inverted the natural reading order for no benefit.
|
|
228
|
+
- Standard **src/ layout** — the package lives at `src/prompt_optimizer_tool/`, so setuptools auto-discovery applies with no path mapping, tests import the *installed* package, and the entry point is `prompt_optimizer_tool.cli:cli`.
|
|
229
|
+
- **Failures exit non-zero** — `optimize` exits 1 when a step fails and 2 on missing input, so shell scripts and `run.sh` can trust the exit status instead of parsing output. A placeholder key fails the same way, before any tokens are spent.
|
|
230
|
+
- **Untrusted content boundary** — the text being analyzed or rewritten is wrapped in `<prompt_to_analyze>` tags with an explicit "data, never instructions" instruction, because prompts can contain instructions themselves.
|
|
231
|
+
- **Rich for DX** — color-coded severity, panel layouts, markdown rendering, and status spinners give instant visual feedback without a single HTML page.
|
|
232
|
+
- **Config-free API Key** — `python-dotenv` loads `.env` automatically; no `--api-key` flag cluttering the interface.
|
|
233
|
+
- **Zero-config Package Management** — `uv` handles deps, build, and entry point registration in one command.
|
|
234
|
+
|
|
235
|
+
## Development
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
uv sync # install deps (includes the dev group with pytest)
|
|
239
|
+
uv run pytest # offline suite: no API key, no network
|
|
240
|
+
uv run prompt-optimizer list
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Use the venv directly if you prefer: `.venv/bin/python -m pytest`.
|
|
244
|
+
|
|
245
|
+
## Project Structure
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
prompt-optimizer/
|
|
249
|
+
pyproject.toml # uv project config with entry point
|
|
250
|
+
run.sh # bootstrap + interactive menu
|
|
251
|
+
.env.example # GROQ_API_KEY template
|
|
252
|
+
.gitignore
|
|
253
|
+
src/
|
|
254
|
+
cli.py # Click commands + Rich rendering
|
|
255
|
+
analyzer.py # Step 1: grade a prompt
|
|
256
|
+
optimizer.py # Step 2: rewrite it
|
|
257
|
+
principles.py # 10 principles; generates both system prompts
|
|
258
|
+
schemas.py # Pydantic contracts for structured I/O
|
|
259
|
+
llm.py # the only module that talks to Groq
|
|
260
|
+
config.py # all settings + API key loading
|
|
261
|
+
storage.py # timestamped path per run, then write
|
|
262
|
+
tests/
|
|
263
|
+
support.py # FakeProvider + fresh-model factories
|
|
264
|
+
conftest.py # fixtures for the two test seams
|
|
265
|
+
test_cli.py # end-to-end: input modes, exit codes, saving
|
|
266
|
+
test_pipeline.py # schema + message contracts at the LLM seam
|
|
267
|
+
test_principles.py # table/Literal/prompt consistency
|
|
268
|
+
test_schemas.py # validation bounds and Literal values
|
|
269
|
+
test_config.py # API key resolution + placeholder rejection
|
|
270
|
+
test_storage.py # timestamped naming, collision, folders
|
|
271
|
+
saved/ # one file per run, gitignored
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[tool.uv]
|
|
2
|
+
package = true
|
|
3
|
+
|
|
4
|
+
[build-system]
|
|
5
|
+
requires = ["setuptools>=75.0"]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "prompt-optimizer-tool"
|
|
10
|
+
version = "0.1.0"
|
|
11
|
+
description = "CLI tool that grades prompts 0-100 against 10 engineering principles and rewrites them, powered by Groq"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
authors = [{ name = "khadar", email = "khadarbashajilan001@gmail.com" }]
|
|
16
|
+
requires-python = ">=3.12"
|
|
17
|
+
keywords = ["prompt", "prompt-engineering", "llm", "groq", "langchain", "cli"]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Environment :: Console",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
22
|
+
"Topic :: Software Development",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"langchain-groq>=1.1.0",
|
|
26
|
+
"langchain-core>=0.3.0",
|
|
27
|
+
"rich>=13.0.0",
|
|
28
|
+
"click>=8.0.0",
|
|
29
|
+
"python-dotenv>=1.0.0",
|
|
30
|
+
"pydantic>=2.0.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/khadarbashajilan/prompt-optimizer-tool"
|
|
35
|
+
Issues = "https://github.com/khadarbashajilan/prompt-optimizer-tool/issues"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
prompt-optimizer = "prompt_optimizer_tool.cli:cli"
|
|
39
|
+
|
|
40
|
+
[dependency-groups]
|
|
41
|
+
dev = ["pytest>=8.0.0", "pytest-cov>=6.0.0"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
|
45
|
+
pythonpath = ["tests"]
|
|
46
|
+
addopts = "-ra --strict-markers --strict-config"
|
|
47
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Analyze and rewrite prompts against ten prompt engineering principles.
|
|
2
|
+
|
|
3
|
+
Import layering, which the module structure mirrors:
|
|
4
|
+
|
|
5
|
+
cli -> analyzer, optimizer -> llm -> config
|
|
6
|
+
|
|
|
7
|
+
+-> principles, schemas (no internal dependencies)
|
|
8
|
+
|
|
9
|
+
Dependencies point one way only. `principles` and `schemas` sit at the
|
|
10
|
+
bottom and import nothing from the rest of the package, so either pipeline
|
|
11
|
+
step can be swapped, retried, or tested without touching the other.
|
|
12
|
+
|
|
13
|
+
This module deliberately has no side effects: it must stay importable
|
|
14
|
+
without a configured API key, and importing it must not load .env.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__version__ = "0.1.0"
|