|
#!/usr/bin/env bash |
|
# |
|
# ai - A simple CLI tool to call the OpenAI Chat API. |
|
# |
|
# Requirements: curl and jq must be installed. |
|
# |
|
# Usage: ./ai [options] prompt... |
|
# |
|
# Options: |
|
# -m MODEL OpenAI model to use (default: gpt-3.5-turbo). |
|
# -j SCHEMA JSONSchema for structured output (optional). |
|
# -k API_KEY Your OpenAI API key (or set the environment variable OPENAI_API_KEY). |
|
# -h Display this help message and exit. |
|
# |
|
|
|
# Default parameter values |
|
MODEL="gpt-4o-mini" |
|
JSON_SCHEMA="" |
|
|
|
usage() { |
|
cat <<EOF |
|
Usage: ${0##*/} [options] prompt... |
|
|
|
Options: |
|
-m MODEL OpenAI model to use (default: ${MODEL}). |
|
-j SCHEMA JSONSchema for structured output (optional). |
|
-k API_KEY Your OpenAI API key (or use the environment variable OPENAI_API_KEY). |
|
-h Display this help message and exit. |
|
|
|
Example: |
|
${0##*/} Tell me a joke about programming |
|
${0##*/} -m gpt-4 What is the meaning of life? |
|
${0##*/} -j '{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"number"}}}' Tell me about John who is 25 |
|
EOF |
|
} |
|
|
|
# Process command-line options |
|
while getopts "m:j:k:h" opt; do |
|
case "$opt" in |
|
m) MODEL="$OPTARG" ;; |
|
j) JSON_SCHEMA="$OPTARG" ;; |
|
k) API_KEY="$OPTARG" ;; |
|
h) |
|
usage |
|
exit 0 |
|
;; |
|
*) |
|
usage |
|
exit 1 |
|
;; |
|
esac |
|
done |
|
|
|
# Remove processed options |
|
shift $((OPTIND-1)) |
|
|
|
# Check if there are any arguments left for the prompt |
|
if [ $# -eq 0 ]; then |
|
echo "Error: Prompt is required." >&2 |
|
usage |
|
exit 1 |
|
fi |
|
|
|
# Concatenate all remaining arguments as the prompt |
|
PROMPT="$*" |
|
|
|
# Determine API key from argument or environment variable |
|
if [ -z "$API_KEY" ]; then |
|
if [ -z "$OPENAI_API_KEY" ]; then |
|
echo "Error: API key not provided. Use -k or set the OPENAI_API_KEY environment variable." >&2 |
|
usage |
|
exit 1 |
|
else |
|
API_KEY="$OPENAI_API_KEY" |
|
fi |
|
fi |
|
|
|
# Build the JSON payload using jq (avoids manual escaping) |
|
if [ -n "$JSON_SCHEMA" ]; then |
|
PAYLOAD=$(jq -n \ |
|
--arg model "$MODEL" \ |
|
--arg prompt "$PROMPT" \ |
|
--argjson schema "$JSON_SCHEMA" \ |
|
'{ |
|
model: $model, |
|
messages: [{role: "user", content: $prompt}], |
|
response_format: { |
|
type: "json_schema", |
|
json_schema: { |
|
name: "response", |
|
schema: $schema |
|
} |
|
} |
|
}') |
|
else |
|
PAYLOAD=$(jq -n \ |
|
--arg model "$MODEL" \ |
|
--arg prompt "$PROMPT" \ |
|
'{ |
|
model: $model, |
|
messages: [{role: "user", content: $prompt}] |
|
}') |
|
fi |
|
|
|
# Call the OpenAI API using curl |
|
response=$(curl -s https://api.openai.com/v1/chat/completions \ |
|
-H "Content-Type: application/json" \ |
|
-H "Authorization: Bearer ${API_KEY}" \ |
|
-d "$PAYLOAD") |
|
|
|
# Check if curl encountered an error |
|
if [ $? -ne 0 ]; then |
|
echo "Error: Failed to contact OpenAI API." >&2 |
|
exit 1 |
|
fi |
|
|
|
# Check if the response contains an error |
|
if echo "$response" | jq -e 'has("error")' > /dev/null; then |
|
error_message=$(echo "$response" | jq -r '.error.message') |
|
echo "Error from OpenAI API: $error_message" >&2 |
|
exit 1 |
|
fi |
|
|
|
echo "$response" | jq -r '.choices[0].message.content' |
|
|