Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/azure openai #42

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ You may then:

### brew

Using Homebrew (ugrades will be available via `brew upgrade please`)
Using Homebrew (upgrades will be available via `brew upgrade please`)

```
```bash
brew tap TNG/please
brew install please
```
Expand Down Expand Up @@ -91,9 +91,11 @@ sudo apt-get install -f
```

### arch

The latest release is in the AUR under the name [please-cli](https://aur.archlinux.org/packages/please-cli). It can be installed [manually](https://wiki.archlinux.org/title/Arch_User_Repository) or with [a helper](https://wiki.archlinux.org/title/AUR_helpers).

Alternatively, you can build the package from source via

```bash
wget https://raw.githubusercontent.com/TNG/please-cli/main/PKGBUILD
makepkg --clean --install --syncdeps
Expand All @@ -113,7 +115,7 @@ sudo chmod +x /usr/local/bin/please

## Prerequisites

You need an OpenAI API key. You can get one here: https://beta.openai.com/. Once logged in, click your account in the top right corner and select "View API Keys". You can then create a new key using the "Create new secret key" button.
You need an OpenAI API key. You can get one here: <https://beta.openai.com/>. Once logged in, click your account in the top right corner and select "View API Keys". You can then create a new key using the "Create new secret key" button.

The API key needs to be set:

Expand Down Expand Up @@ -156,10 +158,10 @@ The model: gpt-4 does not exist
```

The API key you are using is not authorized to use GPT-4. You may also want to use the `--legacy` flag to use GPT-3.5 instead.
You can also apply for GPT4 API access here: https://openai.com/waitlist/gpt-4-api
You can also apply for GPT4 API access here: <https://openai.com/waitlist/gpt-4-api>

## License

Please CLI is published under the Apache License 2.0, see http://www.apache.org/licenses/LICENSE-2.0 for details.
Please CLI is published under the Apache License 2.0, see <http://www.apache.org/licenses/LICENSE-2.0> for details.

Copyright 2023 TNG Technology Consulting GmbH
94 changes: 83 additions & 11 deletions please.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

set -uo pipefail

CONFIG_FILE="${HOME}/.pleaserc"
. $CONFIG_FILE 2>/dev/null

model='gpt-4'
options=("[I] Invoke" "[C] Copy to clipboard" "[Q] Ask a question" "[A] Abort" )
number_of_options=${#options[@]}
Expand All @@ -23,6 +26,7 @@ questionMark="\x1B[31m?\x1B[0m"
checkMark="\x1B[31m\xE2\x9C\x93\x1B[0m"

openai_invocation_url=${OPENAI_URL:-"https://api.openai.com/v1"}
openai_use_azure_endpoint=${OPENAI_URL:+1} # if OPENAI_URL is set, we assume it is an Azure endpoint
fail_msg="echo 'I do not know. Please rephrase your question.'"

declare -a qaMessages=()
Expand All @@ -46,6 +50,10 @@ check_args() {
store_api_key
exit 0
;;
-H|--api-host)
store_api_host
exit 0
;;
-m|--model)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ] && [ "${2:0:3}" == "gpt" ]; then
model="$2"
Expand Down Expand Up @@ -73,6 +81,30 @@ check_args() {
commandDescription="$*"
}

# Write a configuration to disk
#
# Parameters:
# config - The name of the configuration
# value - The value to be set for the configuration
#
# Returns:
# 0 - If the configuration value was successfully written
# 1 - config_key or config_value is empty
function write_config() {
config_key=$1
[ -z $config_key ] && return 1
config_value=$2
[ -z $config_value ] && return 1

[ -f $CONFIG_FILE ] || touch $CONFIG_FILE

sed -i.bak -e "s/^${config_key}=.*\$/${config_key}=${config_value//\//\\/}/w /dev/stdout" $CONFIG_FILE | grep -q .
if [ $? -ne 0 ]; then
echo "${config_key}=${config_value}" >>$CONFIG_FILE
fi
rm "$CONFIG_FILE.bak" # .bak file is created for sed to be compatible with both GNU and BSD sed
}

function store_api_key() {
echo "Do you want the script to store an API key in the local keychain? (y/n)"
read -r answer
Expand All @@ -82,12 +114,14 @@ function store_api_key() {
exit 1
fi

echo "The script needs to create or copy the API key. Press Enter to continue..."
read -rs
if [ "${openai_use_azure_endpoint}" -eq 0 ]; then
echo "The script needs to create or copy the API key. Press Enter to continue..."
read -rs

apiKeyUrl="https://platform.openai.com/account/api-keys"
echo "Opening ${apiKeyUrl} in your browser..."
open "${apiKeyUrl}" || xdg-open "${apiKeyUrl}"
apiKeyUrl="https://platform.openai.com/account/api-keys"
echo "Opening ${apiKeyUrl} in your browser..."
open "${apiKeyUrl}" || xdg-open "${apiKeyUrl}"
fi

while true; do
echo "Please enter your API key: [Press Ctrl+C to exit]"
Expand All @@ -109,6 +143,35 @@ function store_api_key() {
done
}

function store_api_host() {
echo "Setting up Azure OpenAPI host."

while true; do
echo "Please enter your Endpoint: [Press Ctrl+C to exit]"
read -r endpoint

if [ -z "$endpoint" ]; then
echo "Endpoint cannot be empty. Please try again."
else
endpoint=${endpoint%/}
break
fi
done

while true; do
echo "Please enter your Deployment Name: [Press Ctrl+C to exit]"
read -r deployment_id

if [ -z "$deployment_id" ]; then
echo "Deployment Name cannot be empty. Please try again."
else
break
fi
done

write_config "OPENAI_URL" "${endpoint}/openai/deployments/${deployment_id}"
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand - do you want to set endpoint and deployment ID every time you call please - or at least with every new terminal? Wouldn't that be a lot of work? We could also store these values somewhere on the disk, right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving to disk sounds like the right thing to do.
But as the script does not yet do so I didn't make assumptions on how to implement this, but rather start this conversation.

  1. how should we save to disk?
  • ~/.pleaserc
  • ~/.please/config
  • other?
  1. when implementing a config/storage on disk... is there anything of the current state to be migrated?
  • eg: debug or model

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

~/.pleaserc seems like a good location.
I would not sabe model or debug since they are rather transient attributes you might want to change every invocation.

display_version() {
echo "Please vVERSION_NUMBER"
}
Expand All @@ -122,6 +185,7 @@ display_help() {
echo " -l, --legacy Use GPT 3.5 (in case you do not have GPT4 API access)"
echo " --debug Show debugging output"
echo " -a, --api-key Store your API key in the local keychain"
echo " -H, --api-host Store your Azure OpenAPI host"
echo " -m, --model Specify the exact LLM model for the script"
echo " -v, --version Display version information and exit"
echo " -h, --help Display this help message and exit"
Expand Down Expand Up @@ -217,12 +281,20 @@ explain_command() {
}

perform_openai_request() {
IFS=$'\n' read -r -d '' -a result < <(curl "${openai_invocation_url}/chat/completions" \
-s -w "\n%{http_code}" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${OPENAI_API_KEY}" \
-d "${payload}" \
--silent)
if [ "${openai_use_azure_endpoint:-0}" -eq 1 ]; then
endpoint="${openai_invocation_url}/chat/completions?api-version=2023-05-15"
authorization="api-key: ${OPENAI_API_KEY}"
else
endpoint="${openai_invocation_url}/chat/completions"
authorization="Authorization: Bearer ${OPENAI_API_KEY}"
fi

IFS=$'\n' read -r -d '' -a result < <(curl "${endpoint}" \
-s -w "\n%{http_code}" \
-H "Content-Type: application/json" \
-H "${authorization}" \
-d "${payload}" \
--silent)
debug "Response:\n${result[*]}"
length="${#result[@]}"
httpStatus="${result[$((length-1))]}"
Expand Down