struckdown 0.3.11__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.
- struckdown-0.3.11/PKG-INFO +561 -0
- struckdown-0.3.11/README.md +522 -0
- struckdown-0.3.11/pyproject.toml +70 -0
- struckdown-0.3.11/setup.cfg +4 -0
- struckdown-0.3.11/struckdown/__init__.py +781 -0
- struckdown-0.3.11/struckdown/actions/__init__.py +937 -0
- struckdown-0.3.11/struckdown/actions/break_.py +18 -0
- struckdown-0.3.11/struckdown/actions/evidence.py +201 -0
- struckdown-0.3.11/struckdown/actions/fetch.py +48 -0
- struckdown-0.3.11/struckdown/actions/history.py +121 -0
- struckdown-0.3.11/struckdown/actions/markdownify.py +29 -0
- struckdown-0.3.11/struckdown/actions/search.py +206 -0
- struckdown-0.3.11/struckdown/actions/set_.py +16 -0
- struckdown-0.3.11/struckdown/actions/timestamp.py +27 -0
- struckdown-0.3.11/struckdown/cache.py +196 -0
- struckdown-0.3.11/struckdown/data/README.md +1 -0
- struckdown-0.3.11/struckdown/data/butter_robot.txt +45 -0
- struckdown-0.3.11/struckdown/data/meeseeks_box.txt +27 -0
- struckdown-0.3.11/struckdown/data/microverse_battery.txt +23 -0
- struckdown-0.3.11/struckdown/data/plumbus.txt +14 -0
- struckdown-0.3.11/struckdown/data/portal_gun.txt +32 -0
- struckdown-0.3.11/struckdown/errors.py +113 -0
- struckdown-0.3.11/struckdown/execution.py +116 -0
- struckdown-0.3.11/struckdown/grammar.lark +145 -0
- struckdown-0.3.11/struckdown/highlight.py +580 -0
- struckdown-0.3.11/struckdown/incremental.py +67 -0
- struckdown-0.3.11/struckdown/jinja_analysis.py +193 -0
- struckdown-0.3.11/struckdown/jinja_utils.py +233 -0
- struckdown-0.3.11/struckdown/llm.py +517 -0
- struckdown-0.3.11/struckdown/output_formatters.py +227 -0
- struckdown-0.3.11/struckdown/parsing.py +1828 -0
- struckdown-0.3.11/struckdown/playground/__init__.py +18 -0
- struckdown-0.3.11/struckdown/playground/chunking.py +164 -0
- struckdown-0.3.11/struckdown/playground/core.py +544 -0
- struckdown-0.3.11/struckdown/playground/evidence_cache.py +244 -0
- struckdown-0.3.11/struckdown/playground/flask_app.py +1799 -0
- struckdown-0.3.11/struckdown/playground/prompt_cache.py +239 -0
- struckdown-0.3.11/struckdown/playground/static/css/codemirror-struckdown.css +101 -0
- struckdown-0.3.11/struckdown/playground/static/css/playground.css +776 -0
- struckdown-0.3.11/struckdown/playground/static/js/batch-stream.js +475 -0
- struckdown-0.3.11/struckdown/playground/static/js/codemirror-struckdown.js +307 -0
- struckdown-0.3.11/struckdown/playground/static/js/editor.js +2484 -0
- struckdown-0.3.11/struckdown/playground/task_cache.py +323 -0
- struckdown-0.3.11/struckdown/playground/templates/base.html +49 -0
- struckdown-0.3.11/struckdown/playground/templates/editor.html +827 -0
- struckdown-0.3.11/struckdown/playground/templates/partials/inputs_panel.html +27 -0
- struckdown-0.3.11/struckdown/playground/templates/partials/outputs_batch.html +32 -0
- struckdown-0.3.11/struckdown/playground/templates/partials/outputs_single.html +39 -0
- struckdown-0.3.11/struckdown/playground/upload_cache.py +202 -0
- struckdown-0.3.11/struckdown/quarto/sd-highlight/_extension.yml +6 -0
- struckdown-0.3.11/struckdown/quarto/sd-highlight/highlight_fragment.py +225 -0
- struckdown-0.3.11/struckdown/quarto/sd-highlight/sd-highlight.css +144 -0
- struckdown-0.3.11/struckdown/quarto/sd-highlight/sd-highlight.lua +40 -0
- struckdown-0.3.11/struckdown/response_types.py +119 -0
- struckdown-0.3.11/struckdown/results.py +535 -0
- struckdown-0.3.11/struckdown/return_type_models.py +1172 -0
- struckdown-0.3.11/struckdown/sd_cli.py +2133 -0
- struckdown-0.3.11/struckdown/segment_processor.py +747 -0
- struckdown-0.3.11/struckdown/simpletest.py +5 -0
- struckdown-0.3.11/struckdown/static/mermaid.min.js +2029 -0
- struckdown-0.3.11/struckdown/stats.py +568 -0
- struckdown-0.3.11/struckdown/temporal_patterns.py +176 -0
- struckdown-0.3.11/struckdown/tests/__init__.py +1 -0
- struckdown-0.3.11/struckdown/tests/test_actions.py +519 -0
- struckdown-0.3.11/struckdown/tests/test_auto_escaping.py +505 -0
- struckdown-0.3.11/struckdown/tests/test_block_comments.py +171 -0
- struckdown-0.3.11/struckdown/tests/test_cache.py +72 -0
- struckdown-0.3.11/struckdown/tests/test_cache_integration.py +473 -0
- struckdown-0.3.11/struckdown/tests/test_chatter_simple.py +456 -0
- struckdown-0.3.11/struckdown/tests/test_evidence_action.py +357 -0
- struckdown-0.3.11/struckdown/tests/test_incremental.py +247 -0
- struckdown-0.3.11/struckdown/tests/test_jinja_conditionals.py +478 -0
- struckdown-0.3.11/struckdown/tests/test_llm_calls_parallel.py +234 -0
- struckdown-0.3.11/struckdown/tests/test_llm_response_injection.py +603 -0
- struckdown-0.3.11/struckdown/tests/test_optional_completion.py +241 -0
- struckdown-0.3.11/struckdown/tests/test_optional_pick.py +108 -0
- struckdown-0.3.11/struckdown/tests/test_options.py +143 -0
- struckdown-0.3.11/struckdown/tests/test_playground_core.py +280 -0
- struckdown-0.3.11/struckdown/tests/test_playground_e2e.py +665 -0
- struckdown-0.3.11/struckdown/tests/test_playground_flask.py +470 -0
- struckdown-0.3.11/struckdown/tests/test_prompt_cache.py +226 -0
- struckdown-0.3.11/struckdown/tests/test_prompt_injection.py +183 -0
- struckdown-0.3.11/struckdown/tests/test_quantifiers.py +319 -0
- struckdown-0.3.11/struckdown/tests/test_search_action.py +214 -0
- struckdown-0.3.11/struckdown/tests/test_stats.py +374 -0
- struckdown-0.3.11/struckdown/tests/test_system_messages.py +264 -0
- struckdown-0.3.11/struckdown/tests/test_task_cache.py +170 -0
- struckdown-0.3.11/struckdown/tests/test_temperature_overrides.py +171 -0
- struckdown-0.3.11/struckdown/tests/test_temporal_types.py +504 -0
- struckdown-0.3.11/struckdown/tests/test_together.py +660 -0
- struckdown-0.3.11/struckdown/tests/test_type_loader.py +469 -0
- struckdown-0.3.11/struckdown/tests/test_upload_cache.py +214 -0
- struckdown-0.3.11/struckdown/type_loader.py +703 -0
- struckdown-0.3.11/struckdown/types/extract.yaml +13 -0
- struckdown-0.3.11/struckdown/types/poem.yaml +13 -0
- struckdown-0.3.11/struckdown/types/product.yaml +21 -0
- struckdown-0.3.11/struckdown/types/speak.yaml +12 -0
- struckdown-0.3.11/struckdown/types/superhero.yaml +17 -0
- struckdown-0.3.11/struckdown/types/think.yaml +13 -0
- struckdown-0.3.11/struckdown/validation.py +251 -0
- struckdown-0.3.11/struckdown/visualize.py +992 -0
- struckdown-0.3.11/struckdown.egg-info/PKG-INFO +561 -0
- struckdown-0.3.11/struckdown.egg-info/SOURCES.txt +105 -0
- struckdown-0.3.11/struckdown.egg-info/dependency_links.txt +1 -0
- struckdown-0.3.11/struckdown.egg-info/entry_points.txt +2 -0
- struckdown-0.3.11/struckdown.egg-info/requires.txt +33 -0
- struckdown-0.3.11/struckdown.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: struckdown
|
|
3
|
+
Version: 0.3.11
|
|
4
|
+
Summary: struckdown: markdown-like syntax for structured conversations with language models
|
|
5
|
+
Author-email: Ben Whalley <benwhalley@gmail.com>
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: asgiref>=3.7.0
|
|
9
|
+
Requires-Dist: instructor[litellm]>=1.11.0
|
|
10
|
+
Requires-Dist: jinja2>=3.1.6
|
|
11
|
+
Requires-Dist: lark>=1.2.2
|
|
12
|
+
Requires-Dist: pydantic>=2.11.7
|
|
13
|
+
Requires-Dist: python-box>=7.3.2
|
|
14
|
+
Requires-Dist: python-decouple>=3.8
|
|
15
|
+
Requires-Dist: typer>=0.16.0
|
|
16
|
+
Requires-Dist: more-itertools>=10.7.0
|
|
17
|
+
Requires-Dist: jinja-markdown>=1.210911
|
|
18
|
+
Requires-Dist: pytest>=8.4.2
|
|
19
|
+
Requires-Dist: joblib>=1.3.0
|
|
20
|
+
Requires-Dist: dateutils>=0.6.12
|
|
21
|
+
Requires-Dist: openpyxl>=3.1.0
|
|
22
|
+
Requires-Dist: pandas>=2.0.0
|
|
23
|
+
Requires-Dist: rich>=13.0.0
|
|
24
|
+
Requires-Dist: requests>=2.28.0
|
|
25
|
+
Requires-Dist: readability-lxml>=0.8.1
|
|
26
|
+
Requires-Dist: markdownify>=0.14.1
|
|
27
|
+
Requires-Dist: validators>=0.35.0
|
|
28
|
+
Requires-Dist: ddgs>=8.0.0
|
|
29
|
+
Requires-Dist: flask>=3.0.0
|
|
30
|
+
Requires-Dist: flask-limiter>=3.5.0
|
|
31
|
+
Requires-Dist: pytest-xdist>=3.8.0
|
|
32
|
+
Requires-Dist: gunicorn>=21.0.0
|
|
33
|
+
Requires-Dist: filelock>=3.12.0
|
|
34
|
+
Requires-Dist: rank-bm25>=0.2.2
|
|
35
|
+
Provides-Extra: playwright
|
|
36
|
+
Requires-Dist: playwright>=1.40.0; extra == "playwright"
|
|
37
|
+
Provides-Extra: local
|
|
38
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == "local"
|
|
39
|
+
|
|
40
|
+
# struckdown
|
|
41
|
+
|
|
42
|
+
Markdown-based syntax for ***structured*** conversations with language models.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## QuickStart
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install
|
|
49
|
+
uv tool install git+https://github.com/benwhalley/struckdown
|
|
50
|
+
|
|
51
|
+
# Configure
|
|
52
|
+
export LLM_API_KEY="sk-..."
|
|
53
|
+
export LLM_API_BASE="https://api.openai.com/v1"
|
|
54
|
+
|
|
55
|
+
# Try it
|
|
56
|
+
sd chat "Tell me a joke: [[joke]]"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Using a prompt file with actions
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
# sets a config variable to run a web search for "oranges" and
|
|
64
|
+
# summarise the results
|
|
65
|
+
sd chat "[[@search|oranges]] Provide a 2-3 sentence summary [[summary]]"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**[→ Full QuickStart Guide](docs/QUICKSTART.md)**
|
|
69
|
+
|
|
70
|
+
## What is Struckdown?
|
|
71
|
+
|
|
72
|
+
Struckdown makes it easy to extract structured data from text using LLMs with a simple, markdown-inspired syntax.
|
|
73
|
+
|
|
74
|
+
### Example: Batch Processing
|
|
75
|
+
|
|
76
|
+
Imagine you have unstructured data stored in free text. You can make it structured like this:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
% sd batch *.txt "Purpose, <5 words: [[purpose]]"
|
|
80
|
+
[
|
|
81
|
+
{
|
|
82
|
+
"filename": "butter_robot.txt",
|
|
83
|
+
"purpose": "Pass butter, question existence."
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"filename": "plumbus.txt",
|
|
87
|
+
"purpose": "Household universal utility device."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"filename": "portal_gun.txt",
|
|
91
|
+
"purpose": "Interdimensional travel device."
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Example: Type Extraction
|
|
97
|
+
|
|
98
|
+
Extract structured data with type constraints:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
% sd batch *.txt "Price: [[number:price]] Currency? [[pick:currency|schmeckles,brapples,flurbos]]"
|
|
102
|
+
[
|
|
103
|
+
{
|
|
104
|
+
"filename": "butter_robot.txt",
|
|
105
|
+
"price": 18,
|
|
106
|
+
"currency": "schmeckles"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"filename": "plumbus.txt",
|
|
110
|
+
"price": 6.5,
|
|
111
|
+
"currency": "brapples"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Example: Chaining Operations
|
|
117
|
+
|
|
118
|
+
Batch operations accept JSON, so you can chain commands:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
% sd batch *.txt "Purpose: [[purpose]] Name: [[name]]" | \
|
|
122
|
+
sd batch "Most similar on Amazon: [[product]]" -k
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Key Features
|
|
126
|
+
|
|
127
|
+
- **Simple syntax** -- `[[variable]]` for completions, `{{variable}}` for references
|
|
128
|
+
- **System messages** -- Control LLM behavior with `<system>` tags
|
|
129
|
+
- **Type safety** -- Extract booleans, numbers, dates, or pick from options
|
|
130
|
+
- **Token management** -- Use `<checkpoint>` to save tokens between steps
|
|
131
|
+
- **Batch processing** -- Process hundreds of files with progress bars
|
|
132
|
+
- **Caching** -- Automatic disk caching saves money and time
|
|
133
|
+
- **Custom actions** -- Extend with Python functions (RAG, APIs, databases)
|
|
134
|
+
- **Multiple outputs** -- JSON, CSV, Excel, or stdout
|
|
135
|
+
- **Web search and URL fetching** -- Extract data directly from web pages
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
### Command Line
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Extract product data from a web page
|
|
143
|
+
sd chat "{{source}} Extract the product name and price [[product:data]]" \
|
|
144
|
+
-s https://www.example.com/product/12345
|
|
145
|
+
|
|
146
|
+
# Fetch raw HTML (no readability processing)
|
|
147
|
+
sd chat "{{source}} Analyze the HTML structure [[analysis]]" \
|
|
148
|
+
-s https://example.com --raw
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### In Templates (for Batch Processing)
|
|
152
|
+
|
|
153
|
+
Use the `@fetch` action to fetch URLs dynamically within templates:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
[[@fetch:page_content|product_url]]
|
|
157
|
+
|
|
158
|
+
Based on this product page:
|
|
159
|
+
{{page_content}}
|
|
160
|
+
|
|
161
|
+
Extract:
|
|
162
|
+
- Product name: [[name]]
|
|
163
|
+
- Price: [[number:price]]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
With an input spreadsheet containing a `product_url` column:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
sd batch products.xlsx template.sd -o results.xlsx
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Each row's URL will be fetched, processed with readability to extract the main content, and converted to markdown before being passed to the LLM.
|
|
173
|
+
|
|
174
|
+
#### @fetch Parameters
|
|
175
|
+
|
|
176
|
+
| Parameter | Default | Description |
|
|
177
|
+
|-----------|---------|-------------|
|
|
178
|
+
| `url` | required | URL to fetch (unquoted = variable, quoted = literal) |
|
|
179
|
+
| `raw` | `false` | Return raw HTML instead of markdown |
|
|
180
|
+
| `timeout` | `30` | Request timeout in seconds |
|
|
181
|
+
| `max_chars` | `32000` | Max characters (0 = no limit) |
|
|
182
|
+
|
|
183
|
+
Example with parameters:
|
|
184
|
+
```
|
|
185
|
+
[[@fetch:content|url,raw=true,timeout=60,max_chars=0]]
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Documentation
|
|
189
|
+
|
|
190
|
+
### Getting Started
|
|
191
|
+
- **[QuickStart](docs/QUICKSTART.md)** -- Get started in 5 minutes
|
|
192
|
+
- **[CLI Usage](docs/CLI_USAGE.md)** -- Complete command reference
|
|
193
|
+
|
|
194
|
+
### Tutorials
|
|
195
|
+
- **[Building a RAG System](docs/TUTORIAL_RAG.md)** -- Extract → Search → Generate pattern
|
|
196
|
+
- **[Custom Actions](docs/CUSTOM_ACTIONS.md)** -- Extend with Python plugins
|
|
197
|
+
|
|
198
|
+
### Reference
|
|
199
|
+
- **[Examples](examples/)** -- Real-world examples and test cases
|
|
200
|
+
- **[Security](SECURITY.md)** -- Security guidelines and best practices
|
|
201
|
+
|
|
202
|
+
## Installation
|
|
203
|
+
|
|
204
|
+
Requires [UV](https://docs.astral.sh/uv/):
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Install as a tool (recommended)
|
|
208
|
+
uv tool install git+https://github.com/benwhalley/struckdown
|
|
209
|
+
|
|
210
|
+
# Or install in current environment
|
|
211
|
+
uv pip install git+https://github.com/benwhalley/struckdown
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Configuration
|
|
215
|
+
|
|
216
|
+
Set these environment variables:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
export LLM_API_KEY="sk-..." # Your API key
|
|
220
|
+
export LLM_API_BASE="https://api.openai.com/v1" # API endpoint
|
|
221
|
+
export DEFAULT_LLM="gpt-4o-mini" # Model name
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### VSCode Extension
|
|
225
|
+
|
|
226
|
+
Syntax highlighting for `.sd` files:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
cd vscode-extension && ./install.sh
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Select theme: **Cmd/Ctrl+Shift+P** → "Color Theme" → "Struckdown Dark"
|
|
233
|
+
|
|
234
|
+
## Basic Syntax
|
|
235
|
+
|
|
236
|
+
### Completions (Slots)
|
|
237
|
+
|
|
238
|
+
Use `[[slot]]` to mark where the LLM should respond:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
sd chat "Explain quantum physics: [[explanation]]"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Typed Completions
|
|
245
|
+
|
|
246
|
+
Specify the type of response:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Boolean
|
|
250
|
+
sd chat "Is the sky blue? [[bool:answer]]"
|
|
251
|
+
|
|
252
|
+
# Pick from options
|
|
253
|
+
sd chat "Choose [[pick:color|red,green,blue]]"
|
|
254
|
+
|
|
255
|
+
# Numbers
|
|
256
|
+
sd chat "Price: $19.99 [[number:price]]"
|
|
257
|
+
|
|
258
|
+
# Dates
|
|
259
|
+
sd chat "Meeting on Jan 15, 2024 [[date:meeting]]"
|
|
260
|
+
|
|
261
|
+
# JSON (any valid JSON value)
|
|
262
|
+
sd chat "Return data as JSON [[json:data]]"
|
|
263
|
+
|
|
264
|
+
# Record (JSON object with string keys)
|
|
265
|
+
sd chat "Extract as key-value pairs [[record:info]]"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Variables
|
|
269
|
+
|
|
270
|
+
Reference previous extractions with `{{variable}}`:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
Extract name: [[name]]
|
|
274
|
+
|
|
275
|
+
<checkpoint>
|
|
276
|
+
|
|
277
|
+
Hello {{name}}, how are you? [[response]]
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Memory Boundaries
|
|
281
|
+
|
|
282
|
+
Use `<checkpoint>` to create memory boundaries and save tokens:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
Long expensive context...
|
|
286
|
+
|
|
287
|
+
Summary: [[summary]]
|
|
288
|
+
|
|
289
|
+
<checkpoint>
|
|
290
|
+
|
|
291
|
+
Translate {{summary}} to Spanish: [[translation]]
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Everything before `<checkpoint>` is forgotten -- only extracted variables carry forward.
|
|
295
|
+
|
|
296
|
+
## CLI Commands
|
|
297
|
+
|
|
298
|
+
### `sd chat` - Interactive Mode
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
sd chat "Tell me a joke: [[joke]]"
|
|
302
|
+
sd chat -p prompt.sd
|
|
303
|
+
echo "Process this" | sd chat
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### `sd batch` - Batch Processing
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# Basic usage
|
|
310
|
+
sd batch *.txt "Extract [[name]]" -o results.json
|
|
311
|
+
|
|
312
|
+
# With prompt file
|
|
313
|
+
sd batch *.txt -p prompt.sd -o results.csv
|
|
314
|
+
|
|
315
|
+
# Keep input fields
|
|
316
|
+
sd batch *.txt "[[summary]]" -k
|
|
317
|
+
|
|
318
|
+
# Chain operations
|
|
319
|
+
sd batch *.txt "[[purpose]]" | sd batch "Similar: [[product]]" -k
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Output formats** (auto-detected from extension):
|
|
323
|
+
- `.json` -- JSON array
|
|
324
|
+
- `.csv` -- CSV file
|
|
325
|
+
- `.xlsx` -- Excel spreadsheet
|
|
326
|
+
- None -- Pretty-printed to stdout
|
|
327
|
+
|
|
328
|
+
### `sd check` - Validate Prompts
|
|
329
|
+
|
|
330
|
+
Check prompt syntax and display execution plan:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Validate and show structure
|
|
334
|
+
sd check prompt.sd
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Shows system prompt info, sections, completions, dependencies, and line numbers.
|
|
338
|
+
|
|
339
|
+
### `sd graph` - Visualize Prompts
|
|
340
|
+
|
|
341
|
+
Generate dependency graph visualizations:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# Generate HTML visualization (default)
|
|
345
|
+
sd graph prompt.sd
|
|
346
|
+
|
|
347
|
+
# Generate Mermaid diagram text
|
|
348
|
+
sd graph prompt.sd -o diagram.mmd
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Creates interactive diagrams showing sections, completions, dependencies, and execution flow.
|
|
352
|
+
|
|
353
|
+
### `sd flat` - Flatten Templates
|
|
354
|
+
|
|
355
|
+
Resolve all `{% include %}` directives and output flattened template:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
# Output to stdout
|
|
359
|
+
sd flat prompt.sd
|
|
360
|
+
|
|
361
|
+
# Save to file
|
|
362
|
+
sd flat prompt.sd -o flattened.sd
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Useful for debugging includes or creating self-contained templates.
|
|
366
|
+
|
|
367
|
+
## File Includes
|
|
368
|
+
|
|
369
|
+
Struckdown supports file includes using Jinja2's `{% include %}` syntax:
|
|
370
|
+
|
|
371
|
+
```struckdown
|
|
372
|
+
{# Include shared system prompt #}
|
|
373
|
+
{% include 'common/system.sd' %}
|
|
374
|
+
|
|
375
|
+
{# Include evaluation rubric #}
|
|
376
|
+
{% include 'rubrics/essay_criteria.txt' %}
|
|
377
|
+
|
|
378
|
+
Process: {{input}}
|
|
379
|
+
Result: [[output]]
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Search paths** (in priority order):
|
|
383
|
+
1. Same directory as template file
|
|
384
|
+
2. `templates/` subdirectory relative to template file
|
|
385
|
+
3. `./includes/` (project-local includes)
|
|
386
|
+
4. `./templates/` (project-local templates)
|
|
387
|
+
5. `~/.struckdown/includes/` (global user includes)
|
|
388
|
+
|
|
389
|
+
**Advanced includes:**
|
|
390
|
+
|
|
391
|
+
```struckdown
|
|
392
|
+
{# Conditional includes #}
|
|
393
|
+
{% if verbose %}
|
|
394
|
+
{% include 'detailed_instructions.sd' %}
|
|
395
|
+
{% else %}
|
|
396
|
+
{% include 'brief_instructions.sd' %}
|
|
397
|
+
{% endif %}
|
|
398
|
+
|
|
399
|
+
{# Dynamic includes with variables #}
|
|
400
|
+
{% set rubric = 'rubrics/' + grade_level + '.sd' %}
|
|
401
|
+
{% include rubric %}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Caching
|
|
405
|
+
|
|
406
|
+
Struckdown automatically caches LLM responses to disk:
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
# Default cache location
|
|
410
|
+
~/.struckdown/cache # 10 GB limit (LRU eviction)
|
|
411
|
+
|
|
412
|
+
# Disable caching
|
|
413
|
+
export STRUCKDOWN_CACHE=0
|
|
414
|
+
|
|
415
|
+
# Custom cache directory
|
|
416
|
+
export STRUCKDOWN_CACHE=/path/to/cache
|
|
417
|
+
|
|
418
|
+
# Custom size limit (MB)
|
|
419
|
+
export STRUCKDOWN_CACHE_SIZE=5120 # 5 GB
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
## Embeddings
|
|
423
|
+
|
|
424
|
+
Generate text embeddings using API or local models:
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
from struckdown import get_embedding
|
|
428
|
+
|
|
429
|
+
# API embeddings (default)
|
|
430
|
+
embeddings = get_embedding(["text 1", "text 2"])
|
|
431
|
+
|
|
432
|
+
# Local embeddings (requires: uv pip install struckdown[local])
|
|
433
|
+
embeddings = get_embedding(texts, model="local/all-MiniLM-L6-v2")
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Use `local/model-name` prefix for any sentence-transformers model. API embeddings use `LLM_API_KEY` and `LLM_API_BASE` environment variables.
|
|
437
|
+
|
|
438
|
+
## Advanced Features
|
|
439
|
+
|
|
440
|
+
### List Completions
|
|
441
|
+
|
|
442
|
+
Extract multiple items:
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
# Exactly 3 items
|
|
446
|
+
sd chat "Name 3 fruits: [[3*pick:fruit|apple,banana,orange]]"
|
|
447
|
+
|
|
448
|
+
# Between 2 and 4 items
|
|
449
|
+
sd chat "Name 2-4 animals: [[2:4*extract:animals]]"
|
|
450
|
+
|
|
451
|
+
# Any number
|
|
452
|
+
sd chat "List all mentioned: [[*extract:items]]"
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Date/Time Extraction
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
# Single date
|
|
459
|
+
sd chat "Meeting Jan 15 [[date:when]]"
|
|
460
|
+
|
|
461
|
+
# Date range with pattern expansion
|
|
462
|
+
sd chat "Every Tuesday in October [[date*:dates]]"
|
|
463
|
+
|
|
464
|
+
# With validation
|
|
465
|
+
sd chat "Deadline [[!date:deadline]]" # ! makes it required
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Number Extraction
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
# With constraints
|
|
472
|
+
sd chat "Age (0-120): [[number:age|min=0,max=120]]"
|
|
473
|
+
|
|
474
|
+
# Required numbers
|
|
475
|
+
sd chat "Price: [[!number:price]]"
|
|
476
|
+
|
|
477
|
+
# Multiple numbers
|
|
478
|
+
sd chat "Extract all prices: [[number*:prices]]"
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Custom Actions
|
|
482
|
+
|
|
483
|
+
Extend Struckdown with Python functions:
|
|
484
|
+
|
|
485
|
+
```python
|
|
486
|
+
from struckdown import Actions, chatter
|
|
487
|
+
|
|
488
|
+
@Actions.register('uppercase')
|
|
489
|
+
def uppercase_text(context, text: str):
|
|
490
|
+
return text.upper()
|
|
491
|
+
|
|
492
|
+
# Use in template - unquoted 'input' is a variable reference
|
|
493
|
+
result = chatter("[[@uppercase:loud|text=input]]", context={"input": "hello"})
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
See **[Custom Actions Guide](docs/CUSTOM_ACTIONS.md)** for details.
|
|
497
|
+
|
|
498
|
+
### System Messages
|
|
499
|
+
|
|
500
|
+
Control system messages using XML-style `<system>` tags:
|
|
501
|
+
|
|
502
|
+
```
|
|
503
|
+
<system>You are an expert data analyst with 10 years of experience.</system>
|
|
504
|
+
|
|
505
|
+
<system local>Always provide concise, data-driven responses.</system>
|
|
506
|
+
|
|
507
|
+
First analysis: [[analysis1]]
|
|
508
|
+
|
|
509
|
+
<checkpoint>
|
|
510
|
+
|
|
511
|
+
Second analysis: [[analysis2]]
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
**Global system messages** (`<system>`) set the LLM's role and persist across all checkpoints.
|
|
515
|
+
**Local system messages** (`<system local>`) provide instructions that only apply to the current segment.
|
|
516
|
+
|
|
517
|
+
Multiple `<system>` tags append to the system message by default. Use modifiers:
|
|
518
|
+
|
|
519
|
+
```
|
|
520
|
+
<system>Base instructions.</system>
|
|
521
|
+
<system>Additional instructions.</system> <!-- appends -->
|
|
522
|
+
<system replace>Replace all previous.</system> <!-- replaces -->
|
|
523
|
+
|
|
524
|
+
<system local>This segment only.</system> <!-- cleared after checkpoint -->
|
|
525
|
+
<system local replace>New local only.</system> <!-- replaces local -->
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
All support template variables: `{{variable}}`.
|
|
529
|
+
|
|
530
|
+
### Model/Temperature Overrides
|
|
531
|
+
|
|
532
|
+
Override per-slot settings:
|
|
533
|
+
|
|
534
|
+
```
|
|
535
|
+
# Different temperature
|
|
536
|
+
[[think:reasoning|temperature=0.3]]
|
|
537
|
+
|
|
538
|
+
# Different model
|
|
539
|
+
[[pick:choice|red,blue|model=gpt-4]]
|
|
540
|
+
|
|
541
|
+
# Combine
|
|
542
|
+
[[extract:data|model=gpt-4,temperature=0.0]]
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Examples
|
|
546
|
+
|
|
547
|
+
See **[examples/](examples/)** for:
|
|
548
|
+
- Basic completions
|
|
549
|
+
- Multi-step workflows
|
|
550
|
+
- RAG with custom actions
|
|
551
|
+
- Batch processing patterns
|
|
552
|
+
- Date/time extraction
|
|
553
|
+
- Number validation
|
|
554
|
+
|
|
555
|
+
## Contributing
|
|
556
|
+
|
|
557
|
+
Issues and pull requests welcome at [github.com/benwhalley/struckdown](https://github.com/benwhalley/struckdown)
|
|
558
|
+
|
|
559
|
+
## License
|
|
560
|
+
|
|
561
|
+
MIT
|