Skip to content

Commit 77c493a

Browse files
authored
Rename scripts and add json parser. (#160)
1 parent 879eb5f commit 77c493a

File tree

4 files changed

+168
-6
lines changed

4 files changed

+168
-6
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Ailly Prompt Workflow
2+
3+
This project provides two scripts to **generate**, **run**, and **parse** [Ailly](https://www.npmjs.com/package/@ailly/cli) prompts based on your AWS DocGen snippets.
4+
5+
## Overview
6+
7+
1. **Generate** Ailly prompts from DocGen snippets (`make_prompts.py`).
8+
2. **Run** the Ailly CLI on the generated prompts (`npx @ailly/cli`).
9+
3. **Parse** the Ailly outputs back into structured JSON (`parse_json_files.py`).
10+
11+
---
12+
13+
## Prerequisites
14+
15+
- Python 3.8+
16+
- Node.js & npm (for `npx`)
17+
18+
---
19+
20+
## Step 1: Generate Ailly prompts
21+
22+
Use `make_prompts.py` to create a directory of Markdown files and a `.aillyrc` configuration file.
23+
24+
```bash
25+
python make_prompts.py \
26+
--doc-gen-root /path/to/your/docgen/project \
27+
--system-prompts "You are a helpful assistant..." \
28+
--out .ailly_prompts
29+
```
30+
31+
**Arguments:**
32+
- `--doc-gen-root`: Path to your DocGen project root.
33+
- `--system-prompts`: One or more system prompts, either as strings or file paths.
34+
- `--out`: (Optional) Output directory. Defaults to `.ailly_prompts`.
35+
36+
This will:
37+
- Create Markdown files for each snippet.
38+
- Create a `.aillyrc` file with the provided system prompts.
39+
40+
---
41+
42+
## Step 2: Run Ailly CLI
43+
44+
Run Ailly on the generated prompts. From inside the .ailly_prompts directory:
45+
46+
```bash
47+
npx @ailly/cli --root .ailly_prompts
48+
```
49+
50+
This will create `{file}.ailly.md` output files in the `.ailly_prompts` directory (or whatever output directory you specified).
51+
52+
---
53+
54+
## Step 3: Parse Ailly output
55+
56+
After Ailly has generated response files (`*.ailly.md`), parse them into JSON objects using `parse_json_files.py`:
57+
58+
```bash
59+
python parse_json_files.py .ailly_prompts/*.ailly.md --out output.json
60+
```
61+
62+
**Arguments:**
63+
- Positional: List of files to parse (you can use a glob like `*.ailly.md`).
64+
- `--out`: (Optional) Output file path for the resulting JSON array. Defaults to `out.json`.
65+
66+
---
67+
68+
## Example Full Workflow
69+
70+
```bash
71+
# Step 1: Generate prompts
72+
python make_prompts.py \
73+
--doc-gen-root ~/projects/aws-docgen-root \
74+
--system-prompts system_prompt.txt \
75+
--out .ailly_prompts
76+
77+
# Step 2: Run Ailly
78+
npx @ailly/cli --root .ailly_prompts
79+
80+
# Step 3: Parse results
81+
python parse_json_files.py .ailly_prompts/*.ailly.md --out results.json
82+
```

aws_doc_sdk_examples_tools/scripts/make_prompts.py renamed to aws_doc_sdk_examples_tools/agent/make_prompts.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ def parse_prompts_arg(values: List[str]) -> List[str]:
5454
return prompts
5555

5656

57-
def main(doc_gen_root: Path, system_prompts: List[str], out: str = ".ailly_prompts") -> None:
57+
def main(
58+
doc_gen_root: Path, system_prompts: List[str], out: str = ".ailly_prompts"
59+
) -> None:
5860
"""Generate prompts and configuration files for Ailly."""
5961
out_path = Path(out)
6062
setup_ailly(system_prompts, out_path)
@@ -68,17 +70,18 @@ def main(doc_gen_root: Path, system_prompts: List[str], out: str = ".ailly_promp
6870
description="Write Ailly prompts for DocGen snippets and parse the results."
6971
)
7072
parser.add_argument(
71-
"--doc-gen-root", required=True,
72-
help="Path to a DocGen ready project."
73+
"--doc-gen-root", required=True, help="Path to a DocGen ready project."
7374
)
7475
parser.add_argument(
75-
"--system-prompts", nargs="+", required=True,
76-
help="List of prompt strings or file paths to store in a .aillyrc file."
76+
"--system-prompts",
77+
nargs="+",
78+
required=True,
79+
help="List of prompt strings or file paths to store in a .aillyrc file.",
7780
)
7881
parser.add_argument(
7982
"--out",
8083
default=".ailly_prompts",
81-
help="Directory where Ailly prompt files will be written. Defaults to '.ailly_prompts'."
84+
help="Directory where Ailly prompt files will be written. Defaults to '.ailly_prompts'.",
8285
)
8386

8487
args = parser.parse_args()
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import argparse
2+
import json
3+
import logging
4+
from os.path import basename
5+
from pathlib import Path
6+
from typing import List, Dict, Optional
7+
8+
logging.basicConfig(level=logging.WARNING)
9+
logger = logging.getLogger(__name__)
10+
11+
12+
def extract_json_from_text(text: str) -> Optional[Dict]:
13+
brace_stack: List[str] = []
14+
json_start = None
15+
16+
for i, char in enumerate(text):
17+
if char == "{":
18+
if not brace_stack:
19+
json_start = i
20+
brace_stack.append(char)
21+
elif char == "}":
22+
if brace_stack:
23+
brace_stack.pop()
24+
if not brace_stack and json_start is not None:
25+
json_candidate = text[json_start : i + 1]
26+
try:
27+
return json.loads(json_candidate)
28+
except json.JSONDecodeError:
29+
logger.warning(
30+
"Found a brace-balanced block, but it isn't valid JSON."
31+
)
32+
# Continue searching
33+
return None
34+
35+
36+
def process_files(file_paths: List[str]) -> Dict[str, Dict]:
37+
results = {}
38+
for path in file_paths:
39+
try:
40+
with open(path, "r", encoding="utf-8") as f:
41+
content = f.read()
42+
json_data = extract_json_from_text(content)
43+
if json_data is not None:
44+
results[basename(path)] = json_data
45+
else:
46+
logger.warning(f"No valid JSON object found in file: {f.name}")
47+
except Exception as e:
48+
logger.warning(f"Error processing file {path}: {e}")
49+
return results
50+
51+
52+
def write_objects(object: Dict, out: Path):
53+
out.write_text(json.dumps(object, indent=2))
54+
55+
56+
def main():
57+
parser = argparse.ArgumentParser(
58+
description="Extract JSON objects from one or more text files."
59+
)
60+
61+
parser.add_argument("files", nargs="+", help="List of files to process")
62+
63+
parser.add_argument(
64+
"--out",
65+
default="out.json",
66+
help="File path where the resultant json will be written.",
67+
)
68+
69+
args = parser.parse_args()
70+
71+
json_objects = process_files(args.files)
72+
out = Path(args.out)
73+
write_objects(json_objects, out)
74+
75+
76+
if __name__ == "__main__":
77+
main()
File renamed without changes.

0 commit comments

Comments
 (0)