Skip to content

Instantly share code, notes, and snippets.

@sadasant
Last active August 30, 2023 17:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sadasant/0bd54012fa63ea0cbd3d711a6e700d66 to your computer and use it in GitHub Desktop.
Save sadasant/0bd54012fa63ea0cbd3d711a6e700d66 to your computer and use it in GitHub Desktop.
Bash function for piping command outputs to OpenAI's GPT-4 model

This gpt() function reads input from the command line and then sends a formatted JSON object to the OpenAI API for the GPT-4 model. It properly escapes special characters and checks for the .env file containing the OpenAI API key.

Usage:

  • Load the function into your environment: source gpt.sh.
  • Make sure to have an .env file in the current directory with the OPENAI_API_KEY.
  • Pipe anything itno it, and also add a prompt, example:
git diff main | gpt "As a programmer, review this diff. Provide feedback only if necessary. Be brief"

Or, to specify the model:

git diff main | gpt -m gpt-4-32k -p "As a programmer, review this diff. Provide feedback only if necessary. Be brief"

Or you can use <<< to make it easier to switch what you want to pipe into the gpt command:

gpt -m gpt-4-32k -p "As a programmer, review this diff. Provide feedback only if necessary. Be brief" <<< $(git diff main ./)
function gpt() {
# If neither .env exists, nor the $OPENAI_API_KEY is set, return error
if [ ! -r ".env" ] && [ -z "$OPENAI_API_KEY" ]; then
echo "ERROR: .env file not found, or OPENAI_API_KEY is not set"
return 1
fi
# Read .env file if exists and is readable
if [ -r ".env" ]; then
set -o allexport; source .env; set +o allexport
elif [ -z "$OPENAI_API_KEY" ]; then
# If .env file does not exist, and OPENAI_API_KEY is not set, return error
echo "ERROR: OPENAI_API_KEY is not set"
return 1
fi
local model="gpt-4"
local prompt
# Check for -m and -p flags
while getopts "m:p:" opt; do
case ${opt} in
m)
model="${OPTARG}"
;;
p)
prompt="${OPTARG}"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
return 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
return 1
;;
esac
done
shift $((OPTIND -1))
# If no prompt is provided through -p, use the first positional argument
if [ -z "$prompt" ]; then
prompt="$1"
fi
# Check that prompt is provided
if [ -z "$prompt" ]; then
echo "ERROR: No prompt provided"
return 1
fi
echo "Model: $model"
echo "Prompt: $prompt"
# Read piped input into a variable
local pipe_input=""
while IFS= read -r line
do
pipe_input+="$line"$'\n'
done
echo "Context length: ${#pipe_input}"
# Properly escape JSON values using jq
local json_prompt
json_prompt=$(printf '%s' "$prompt" | jq --raw-input --slurp .)
local json_pipe_input
json_pipe_input=$(printf '%s' "$pipe_input" | jq --raw-input --slurp .)
echo -e "Response:\n"
# Call OpenAI API
curl --progress-bar --location --insecure \
--request POST 'https://api.openai.com/v1/chat/completions' \
--header "Authorization: Bearer $OPENAI_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw "{
\"model\": \"$model\",
\"messages\": [{\"role\": \"system\", \"content\": $json_prompt},{\"role\": \"user\", \"content\": $json_pipe_input}]
}" | jq --raw-output '.choices[].message.content'
}
@gubatron
Copy link

$ diff -u gpt.sh gpt2.sh
--- gpt.sh	2023-06-23 15:09:31
+++ gpt2.sh	2023-06-23 15:10:02
@@ -1,4 +1,10 @@
 function gpt() {
+  # Check that OPENAI_API_KEY is set
+  if [ -z "$OPENAI_API_KEY" ]; then
+    echo "ERROR: OPENAI_API_KEY is not set"
+    return 1
+  fi
+
   # Check that argument is provided
   if [ -z "$1" ]; then
     echo "ERROR: No prompt provided"
@@ -28,13 +34,6 @@
 
   # Read .env file
   set -o allexport; source .env; set +o allexport
-
-  # Check that OPENAI_API_KEY is set
-  if [ -z "$OPENAI_API_KEY" ]; then
-    echo "ERROR: OPENAI_API_KEY is not set"
-    return 1
-  fi
-
   echo -e "Response:\n"
 
   # Call OpenAI API

My silly patch is to make the check for the OPENAI_API_KEY first thing, don't bother doing any work if this isn't set.

@sadasant
Copy link
Author

that won't work for me, since I generally store it in the .env file that I read in the line set -o allexport; source .env; set +o allexport

@gubatron
Copy link

oh, I see:

# Read .env file
  set -o allexport; source .env; set +o allexport

  # Check that OPENAI_API_KEY is set
  if [ -z "$OPENAI_API_KEY" ]; then
    echo "ERROR: OPENAI_API_KEY is not set"
    return 1
  fi

Got it, got it.

Then just include that line before checking

@gubatron
Copy link

in fact, I'd make that check conditionally.

is the OPENAI_API_KEY set? if so, don't even bother loading source .env
Otherwise, try loading it, and check again.

There might be other geeks like me that do set the OPENAI_API_KEY in their .bash_profile

@sadasant
Copy link
Author

Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment