Skip to content

Instantly share code, notes, and snippets.

@u1and0
Last active July 20, 2023 00:41
Show Gist options
  • Save u1and0/b4a8647bebbcb8b9b71c6e166726063e to your computer and use it in GitHub Desktop.
Save u1and0/b4a8647bebbcb8b9b71c6e166726063e to your computer and use it in GitHub Desktop.
Ask ChatGPT from terminal
#!/bin/sh
# ChatGPT client by ShellScript
# $ curlgpt "hello world!"
# or
# $ echo "hello world!" | curlgpt
#
# MIT License
#
# Copyright (c) 2023 u1and0
# ローディングスピナーを表示します。
# `$1`には、バックグラウンドで実行されるプロセスのPIDを渡します。
# スピナーのフレームは、`spinstr`変数に保存されます。
# `printf`コマンドを使用して、スピナーの各フレームを表示し、
# `sleep`コマンドを使用して、スピナーの速度を調整します。
# 最後に、`printf`コマンドを使用して、スピナーを消去します。
_spinner() {
local pid=$1
local delay=0.02
local spinstr='.'
while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
printf " %s " "$spinstr"
local spinstr=$spinstr'.'
sleep $delay
printf "\b\b\b\b\b\b\b"
if [ ${#spinstr} -gt 3 ]; then
spinstr='.'
fi
done
printf " \b\b\b\b"
}
# Remove temp file
_cleanup() {
rm -f "$response_file"
}
# MAIN
# Default values
model="gpt-3.5-turbo"
temperature=1.0
max_tokens=1000
system_prompt=""
USAGE=$(cat <<-END
Usage:
$ curlgpt "hello world!"
or
$ echo "hello world!" | curlgpt
Options:
-m: OpenAI model name (default to gpt-3.5-turbo)
-t: temperature value (default to 1.0)
-x: max_tokens value (default to 1000)
-s: system prompt
END
)
# Options
while getopts ":m:t:x:s:h:" option; do
case "${option}" in
m) model=${OPTARG};;
t) temperature=${OPTARG};;
x) max_tokens=${OPTARG};;
s) system_prompt=${OPTARG};;
h) echo "${USAGE}"; exit 0;;
\?) echo "Invalid option: -$OPTARG" 1>&2; exit 1;; # 不正なオプション
:) echo "${USAGE}" 1>&2; exit 1;; # オプション引数がない
esac
done
shift $(expr $OPTIND - 1)
# Get input from stdin or arg
if [ -p /dev/stdin ]; then
# パイプラインからの入力がある場合
input=$(cat - | xargs | sed -e 's/"/\"/g' | tr -d '[:cntrl:]' 2> /dev/null)
elif [ -n "$1" ]; then
# 引数がある場合
input="$1"
else
# 引数がなく、パイプラインからの入力もない場合
printf '%s\n' "${USAGE}"
exit 1
fi
# curlgpt
# curlでchatgptに第一引数の文字列の質問
# jqでcontentのみ表示
response_file="$(mktemp)"
messages=$(cat <<-END
{ "role":"system", "content": "${system_prompt}" },
{ "role":"user", "content": "${input}" }
END
)
data=$(cat <<-END
{
"model": "${model}",
"temperature": ${temperature},
"max_tokens": ${max_tokens},
"messages": [${messages}]
}
END
)
echo -e "${data}" >&2
curl -s -X POST https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${OPENAI_API_KEY}" \
-d "${data}" -o "$response_file" 2>&1 &
curl_pid=$!
# curlが終わるまでスピナー表示
_spinner "$curl_pid" >&2
wait "$curl_pid"
# curlの終了ステータスによってjqの表示を変える
curl_status=$?
error_response="$(cat "$response_file" | jq '.error')"
if [ "$curl_status" -eq 0 ] && [ "${error_response}" == "null" ]; then
s=$( cat "$response_file" | jq -r '.choices[].message.content' )
# print char by char
while [ ${#s} -gt 0 ]; do
printf '%s' "${s%${s#?}}"
s=${s#?}
sleep 0.02
done
printf '\n'
else
echo -e "data: ${data}" >&2
cat "$response_file" | jq -r
fi
trap _cleanup EXIT
trap "kill $curl_pid && _cleanup" SIGINT SIGTERM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment