Last active
April 30, 2024 19:44
-
-
Save xpepper/6c194e87183550f54affef78acc8f638 to your computer and use it in GitHub Desktop.
An AI-driven git commit message generator. It needs a valid OpenAI key set as an env variable`OPENAI_API_KEY`. It works on macOS, needs curl and jq in order to work.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
OPENAI_API_KEY="${OPENAI_API_KEY}" | |
HOST="https://api.openai.com" | |
MODEL="gpt-3.5-turbo" | |
# Check if the API key is set | |
if [ -z "$OPENAI_API_KEY" ]; then | |
echo "OpenAI API key is not set. Please set the OPENAI_API_KEY environment variable." | |
exit 1 | |
fi | |
# Get the diff of staged changes | |
DIFF=$(git diff --staged) | |
# Check if there are any staged changes | |
if [ -z "$DIFF" ]; then | |
echo "No changes are staged for commit." | |
exit 1 | |
fi | |
# Escape special JSON characters in the diff output | |
# This uses Perl instead of sed for better cross-platform compatibility | |
ESCAPED_DIFF=$(echo "content: $DIFF" | perl -pe 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g; s/\r//g;') | |
# Prepare the data for the API request | |
read -r -d '' DATA <<EOF | |
{ | |
"model": "$MODEL", | |
"messages": [ | |
{"role": "system", "content": "You are a git message commit generator. You get a set of file changes and you generate a proper git commit message, following the Conventional Commits standard. Don't add any other info if not related to the changes themselves."}, | |
{"role": "user", "content": "$ESCAPED_DIFF"} | |
], | |
"max_tokens": 250, | |
"temperature": 0.3 | |
} | |
EOF | |
# Make the API request to OpenAI using the chat completions endpoint | |
RESPONSE=$(curl -s "$HOST/v1/chat/completions" \ | |
-H "Content-Type: application/json" \ | |
-H "Authorization: Bearer $OPENAI_API_KEY" \ | |
-d "$DATA") | |
# Extract the commit message from the response | |
COMMIT_MESSAGE=$(echo $RESPONSE | jq -r '.choices[0].message.content') | |
# Output the commit message | |
echo "Here's a commit message based on the diff:" | |
echo "$COMMIT_MESSAGE" |
A Python version:
import subprocess
import json
import os
import requests
def get_git_diff():
"""Get the staged git diff."""
return subprocess.run(['git', 'diff', '--staged'], stdout=subprocess.PIPE).stdout.decode('utf-8')
def escape_diff(diff):
"""Escape special JSON characters in the git diff."""
return diff.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r')
def generate_commit_message(diff):
"""Generate a commit message using OpenAI's API."""
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
print("OpenAI API key is not set. Please set the OPENAI_API_KEY environment variable.")
return
if not diff:
print("No changes are staged for commit.")
return
escaped_diff = escape_diff(diff)
data = {
"model": "gpt-3.5-turbo",
"messages": [
{"role": "system", "content": "You are a git message commit generator. You get a set of file changes and you generate a proper git commit message, following the Conventional Commits standard. Don't add any other info if not related to the changes themselves."},
{"role": "user", "content": escaped_diff}
],
"max_tokens": 250,
"temperature": 0.3
}
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {api_key}'
}
response = requests.post('https://api.openai.com/v1/chat/completions', headers=headers, json=data)
if response.status_code == 200:
commit_message = response.json()['choices'][0]['message']['content']
print("Here's a commit message based on the diff:")
print(commit_message)
else:
print("Failed to generate commit message:", response.text)
if __name__ == '__main__':
diff = get_git_diff()
generate_commit_message(diff)
Another Python version using openai
lib
import subprocess
import os
from openai import OpenAI
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
print("OpenAI API key is not set. Please set the OPENAI_API_KEY environment variable.")
exit()
model = "gpt-3.5-turbo"
# model = "llama-3-70b-instruct"
client = OpenAI(api_key=api_key, base_url="https://api.openai.com/v1")
# client = OpenAI(api_key=api_key, base_url="https://api.perplexity.ai")
def get_git_diff():
"""Get the staged git diff."""
return subprocess.run(['git', 'diff', '--staged'], stdout=subprocess.PIPE).stdout.decode('utf-8')
def escape_diff(diff):
"""Escape special JSON characters in the git diff."""
return diff.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r')
def generate_commit_message(diff):
if not diff:
print("No changes are staged for commit.")
return
escaped_diff = escape_diff(diff)
try:
response = client.chat.completions.create(model=model,
messages=[
{"role": "system", "content": "You are a git message commit generator. You get a set of file changes and you generate a proper git commit message, following the Conventional Commits standard. Don't add any other info if not related to the changes themselves."},
{"role": "user", "content": escaped_diff}
],
max_tokens=250,
temperature=0.3)
commit_message = response.choices[0].message.content
print(commit_message)
except Exception as e:
print("Failed to generate commit message:", str(e))
if __name__ == '__main__':
diff = get_git_diff()
generate_commit_message(diff)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I did it with some help from Perplexity. See https://www.perplexity.ai/search/Id-like-to-cEyl3pg8Sc6t9YtO.t75NQ