Skip to content

Instantly share code, notes, and snippets.

@bas080
Last active June 9, 2023 14:26
Show Gist options
  • Save bas080/2268473a12af12320d366b9dce7a0f6a to your computer and use it in GitHub Desktop.
Save bas080/2268473a12af12320d366b9dce7a0f6a to your computer and use it in GitHub Desktop.

$ cat ./README.md ./gpt | gpt Please update the README > README.md

Just kidding, I wrote the readme... or did I?

$ gpt

This Bash script uses the OpenAI API to generate a response to a user-specified query using the GPT-3 language model. The response is appended to a specified context file, which contains the history of messages and responses.

Requirements

To use this script, you will need:

  • Bash (version 4 or later)
  • curl
  • jq
  • pandoc (optional pretty printing to terminal)
  • elinks (optional retty printing to terminal)

You will also need an OpenAI API key, which can be obtained from the OpenAI website.

Installation

  1. Copy paste the script in a $PATH directory.
  2. Make the script executable with chmod +x gpt.
  3. Add export OPENAI_KEY="your-api-key" to your .bashrc.

You can now run the script.

Note: If you do not wish to export your OpenAI API key, you can include it directly in the script by replacing $OPENAI_KEY with your actual API key.

Usage

To run the script, use the following command:

gpt                   # Opens the context file for editing.
gpt Hellp gpt         # Uses the arguments as input.
stdin | gpt           # Uses the stdin as user input.
stdin | gpt Hello gpt # Uses stdin + arguments as input.

It's important to know that you can configure gpt using the environment variables. I create gpt aliases for different tasks. Here is a list of those variables and their default values.

OPENAI_KEY="${OPENAI_KEY:?OPENAI_KEY is not set}"
OPENAI_MODEL="${OPENAI_MODEL:-gpt-3.5-turbo}"
OPENAI_CONTEXT="${OPENAI_CONTEXT:-/tmp/gpt.$WINDOWID}"
OPENAI_PROMPT="${OPENAI_PROMPT:-/tmp/gpt.$WINDOWID.prompt}"
OPENAI_TOKENS="${OPENAI_TOKENS:-4096}"

$WINDOWID is unique for every terminal you open. This allows you to spawn a new terminal and start with a clean slate.

alias programmer-gpt='OPENAI_PROMPT="$HOME/programmer.prompt" gpt'
alias git-gpt='OPENAI_PROMPT="$HOME/git.prompt" gpt'
#!/usr/bin/env bash
set -eou pipefail
# Set default environment variables
readonly OPENAI_API="https://api.openai.com/v1/chat/completions"
readonly OPENAI_KEY="${OPENAI_KEY:?OPENAI_KEY is not set}"
readonly OPENAI_MODEL="${OPENAI_MODEL:-gpt-3.5-turbo}"
readonly OPENAI_CONTEXT="${OPENAI_CONTEXT:-/tmp/gpt.$WINDOWID}"
readonly OPENAI_PROMPT="${OPENAI_PROMPT:-/tmp/gpt.$WINDOWID.prompt}"
readonly OPENAI_TOKENS="${OPENAI_TOKENS:-4096}"
# Create the prompt file if it doesn't exist
if [ ! -f "$OPENAI_PROMPT" ]; then
echo 'You are a helpful assistant that answers questions.
You print valid markdown.' > "$OPENAI_PROMPT"
fi
echo -e "\n$OPENAI_PROMPT"
cat "$OPENAI_PROMPT" 1>&2
echo
# Function to handle script exits and print error messages
function handle_exit {
local status=$?
if [ $status -ne 0 ]; then
echo "Script failed with status code $status on command: $BASH_COMMAND" >&2
fi
}
trap handle_exit EXIT
# If no arguments and no stdin
if [ -z "$*" ] && [ -t 0 ]; then
if [ -t 1 ]; then
"$EDITOR" "$OPENAI_CONTEXT"
else
cat "$OPENAI_CONTEXT"
exit 0
fi
fi
# If input is provided, append it to the context file
if [ ! -t 0 ]; then
cat - >> "$OPENAI_CONTEXT"
fi
# Append any arguments to the context file
if [ -n "$*" ]; then
echo "$*" >> "$OPENAI_CONTEXT"
fi
# Function to create the prompt object for OpenAI API
function create_prompt {
jq --raw-input '{"role": "system", "content": .}' < "$OPENAI_PROMPT" | jq --slurp
}
function pretty_print {
if [ -t 1 ] ; then
pandoc -f markdown -t html - | elinks --dump --dump-color-mode 1
else
cat -
fi
}
# TODO: change temperature, and/or presence/frequency penalty settings in order to unlobotomise the bot a little more.
# Build the message object and send it to OpenAI API with curl
jq --null-input \
--arg MODEL "$OPENAI_MODEL" \
--argfile PROMPT <(create_prompt) \
--rawfile MESSAGE <(tail -c "$OPENAI_TOKENS" "$OPENAI_CONTEXT") '{
"model": $MODEL,
"messages": [
$PROMPT[],
{
"role": "user",
"content": $MESSAGE
}
]
}' | curl --fail-early -s \
--no-buffer \
-H "Authorization: Bearer $OPENAI_KEY" \
-H "Content-Type: application/json" \
-X POST \
--data-binary @- "$OPENAI_API" |
jq -e -r '.choices[0].message.content' |
tee -a "$OPENAI_CONTEXT" |
pretty_print
@bas081
Copy link

bas081 commented May 28, 2023

Thanks @mountaineerbr, I assume you meant wrapper; warper sounds way cooler though. I might borrow an idea or two from your script, but this gist is meant to stay a simple warper.

@mountaineerbr
Copy link

@bas081 OK, I understand. That is worthwhile to have your own chatgpt script, at least you know exactly what is going on!
If I may point it out, perhaps setting temperature, and/or presence/frequency penalty is in order to unlobotomise the bot a little more..
The guys at The Linux Link Tech Show use the word "warp" as a verb for describing what some programmes do, not as agentive noun which is grammatically wrong, but you get the gist! Cheers!

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