Last active
March 25, 2024 02:20
-
-
Save PurpleBooth/974e84f2801e42e81b3f07d80b321afd to your computer and use it in GitHub Desktop.
I cba with writing my own commit messages anymore
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
#!/usr/bin/env python | |
import json | |
import logging | |
import subprocess | |
import sys | |
import textwrap | |
from typing import Literal, Sequence, TypedDict, Union | |
from urllib.error import HTTPError | |
from urllib.request import Request, urlopen | |
api_key = "replaceme" | |
class Message(TypedDict): | |
role: Union[Literal["system"], Literal["assistant"], Literal["user"]] | |
content: str | |
def get_subject(summary: str, diff: str) -> tuple[str, list[Message]]: | |
messages: list[Message] = [ | |
{ | |
"role": "system", | |
"content": "You are a tool that explains code changes", | |
}, | |
{"role": "user", "content": "Can you explain change?"}, | |
{ | |
"role": "assistant", | |
"content": "Sure, do you have any information other than the diff?", | |
}, | |
{"role": "user", "content": summary}, | |
{"role": "assistant", "content": "Can you provide me the diff?"}, | |
{"role": "user", "content": diff}, | |
{ | |
"role": "assistant", | |
"content": "Here is a terse, 50-character summary of the changes in the imperative tense", | |
}, | |
] | |
result = do_request(messages) | |
return result, messages + [{"role": "assistant", "content": result}] | |
def get_body(previous: Sequence[Message]) -> str: | |
messages: list[Message] = list(previous) + [ | |
{ | |
"role": "user", | |
"content": "Can you give me a longer description of the changes?", | |
}, | |
{ | |
"role": "assistant", | |
"content": "Sure, what follows is a longer description of the changes in the imperative tense", | |
}, | |
] | |
return do_request(messages) | |
def do_request(messages: Sequence[Message]) -> str: | |
request = { | |
"model": "gpt-3.5-turbo", | |
"messages": messages, | |
} | |
body = json.dumps(request) | |
httprequest = Request( | |
"https://api.openai.com/v1/chat/completions", | |
method="POST", | |
headers={ | |
"Content-Type": "application/json", | |
"Authorization": f"Bearer {api_key}", | |
}, | |
) | |
try: | |
with urlopen(httprequest, data=body.encode("utf-8")) as response: | |
response_body = response.read().decode() | |
return json.loads(response_body)["choices"][0]["message"]["content"] | |
except HTTPError as e: | |
logging.exception(e.read().decode()) | |
raise e from e | |
hint = "No" | |
if len(sys.argv) > 1: | |
hint = " ".join(sys.argv[1:]) | |
diff_output = subprocess.run( | |
["git", "diff", "--patch", "--cached"], capture_output=True | |
) | |
diff_output.check_returncode() | |
subject, messages = get_subject(hint, diff_output.stdout.decode()) | |
subject = subject.rstrip(".") | |
body = get_body(messages).split("\n\n") | |
wrapped_subject = [subject] | |
if len(subject) > 72: | |
body = [subject] + body | |
subject = textwrap.shorten(subject, width=50) | |
wrapped_subject = [subject] | |
wrapped_paragraphs = [ | |
textwrap.fill( | |
s, | |
width=72, | |
) | |
for s in body | |
] | |
wrapped_text = "\n\n".join( | |
wrapped_subject + wrapped_paragraphs, | |
) | |
print(wrapped_text) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment