-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathchatgptjq
executable file
·95 lines (83 loc) · 2.96 KB
/
chatgptjq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/bin/bash
# Reproduces https://simonwillison.net/2024/Oct/27/llm-jq/ - what a great idea by Simon Willison!
# print usage if there are no arguments $1 is -h or --help
function usage() {
echo "Extracts from a JSON file read from stdin by applying a jq command generated by ChatGPT from your prompt"
echo "Usage e.g.: cat jsonfile | $0 prompt"
echo "Additional options:"
echo " -f jsonfile: read the JSON from the file jsonfile instead of stdin"
echo " -h, --help, -?: print this help message"
echo " -v, --verbose: print the request sent to the LLM"
echo " -s, --silent: do not print the command run with jq"
echo " -n, --no-run: print the command line but do not run it."
}
if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "-?" ]; then
usage
exit 0
fi
# parse the options
verbose=""
silent=false
jsonfile=""
norun=false
while [ "$#" -gt 0 ]; do
case $1 in
-f) jsonfile=$2; shift 2 ;;
-v|--verbose) verbose="-v"; shift ;;
-s|--silent) silent=true; shift ;;
-n|--no-run) norun=true; shift ;;
-h|--help|-?) usage; exit 0 ;;
*) break ;;
esac
done
prompt="$*"
jqgenerateprompt=$(cat << EOF
Based on the printed JSON snippet and the desired query, print jq arguments that fulfill that query.
Print as JSON the query as you understand it, then explain how you would extract the desired information,
and as last item print the arguments for jq - e.g. ["-r", "sort_by(.name)[] | .name"]. Do not additionally quote the arguments.
EOF
)
if [ -z "$jsonfile" ]; then
jsonfile=$(mktemp -u).json
trap 'rm -f $jsonfile' EXIT
cat > $jsonfile
if [ "$?" -ne 0 ]; then
echo "Error reading JSON from stdin"
exit 1
fi
else
if [ ! -f "$jsonfile" ]; then
echo "Error: file $jsonfile does not exist"
exit 1
fi
fi
# generate the jq command
jqcmd=$(head -c 1000 $jsonfile | chatgpt $verbose -f - -ra queryasunderstood,explanation,a:jqargs -s "$jqgenerateprompt" "$prompt")
if [ "$?" -ne 0 ]; then
echo "Error generating jq command"
exit 1
fi
# that looks like
# {"queryasunderstood":"Create a jq filter to count issues by user login and display the top 3.","explanation":"This filter processes the input JSON array to group issues by user login, counts the occurrences of each login, sorts them in descending order, and picks the top 3.","jqargs":["-r", "map(.user.login) | group_by(.) | map({login: .[0], count: length}) | sort_by(-.count) | .[:3]"]}
queryasunderstood=$(echo $jqcmd | jq -r .queryasunderstood)
explanation=$(echo $jqcmd | jq -r .explanation)
jqargs=()
while read -r line; do
# echo line $line
jqargs+=("$line")
done < <(echo $jqcmd | jq -r .jqargs[])
if [ "$silent" = false ]; then
echo "Query as understood: $queryasunderstood"
echo "Explanation: $explanation"
echo "jq command: " "$(echo $jqcmd | jq -c .jqargs)"
fi
# run the jq command
if [ "$norun" = true ]; then
exit 0
fi
jq -r "${jqargs[@]}" $jsonfile
result=$?
if [ "$result" -ne 0 ]; then
echo "Error $result running jq command"
exit $?
fi