Skip to content

Instantly share code, notes, and snippets.

@PurpleBooth
Last active March 25, 2024 02:20
Show Gist options
  • Save PurpleBooth/974e84f2801e42e81b3f07d80b321afd to your computer and use it in GitHub Desktop.
Save PurpleBooth/974e84f2801e42e81b3f07d80b321afd to your computer and use it in GitHub Desktop.
I cba with writing my own commit messages anymore
#!/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