matteopilotto/github-issue-summarizer
1
1import os2import requests3from datetime import datetime4 5import gradio as gr6from gradio import components7 8import openai9from langchain_openai import ChatOpenAI10from langchain.chains.summarize import load_summarize_chain11from langchain.docstore.document import Document12 13def comment_datetime(comment_json):14 dt = datetime.fromisoformat(comment_json["created_at"][:-1])15 return comment_json["user"]["login"] + " commented on " + dt.strftime("%b %d, %Y") + ":"16 17str_format = """18{author}\n19{comment}20""".strip()21 22def get_comments(url):23 response = requests.get(url, headers=None)24 json_content = response.json()25 comments = "<|endoftext|>".join([str_format.format(author=comment_datetime(x).strip(), comment=x["body"].strip()) for x in json_content])26 27 return comments28 29 30template = """31### ISSUE #{issue_num}\n32### TITLE: {title}\n33### URL: {html_url}\n34### LABELS: {labels}\n35### BODY:\n36{body}\n37### COMMENTS:\n38{comments}\n39""".strip()40 41def get_full_context(row):42 labels = row["labels"].split("<|endoftext|>")43 comments = row["comments"].replace("<|endoftext|>", "\n\n")44 context = template.format(45 issue_num=row["issue_num"],46 url=row["url"],47 comments_url=row["comments_url"],48 html_url=row["html_url"],49 title=row["title"],50 labels=labels,51 body=row["body"],52 comments=comments53 )54 55 return context56 57 58def get_issue_info(url):59 url_items = url.split("/")60 url_api = "https://api.github.com/repos/{}/{}/issues/{}".format(url_items[-4], url_items[-3], url_items[-1])61 headers = {"Authorization": f"token {os.getenv('GITHUB_TOKEN')}"}62 response = requests.get(url_api, headers=None)63 issue = response.json()64 issue_short = {k: v for k, v in issue.items() if k in ["id", "url", "comments_url", "html_url", "title", "body"]}65 issue_short["labels"] = "<|endoftext|>".join([x["name"] for x in issue["labels"]])66 issue_short["issue_num"] = issue["number"]67 issue_short["comment_count"] = issue["comments"]68 69 # get comments70 issue_short["comments"] = get_comments(issue_short["comments_url"])71 72 # get context73 context = get_full_context(issue_short)74 75 return context76 77 78def init_chain(openai_api_key):79 llm = ChatOpenAI(80 model_name="gpt-4o",81 temperature=0.0,82 openai_api_key=openai_api_key83 )84 85 chain = load_summarize_chain(llm, chain_type="stuff")86 87 return chain88 89 90def get_summary(text, chain):91 doc = Document(page_content=text)92 summary = chain.invoke([doc])["output_text"].strip()93 94 return summary95 96 97template_output = """98## SUMMARY ๐99### {summary}100***101## Source ๐พ102{context}103""".strip()104 105def run_all(openai_api_key, url):106 try:107 context = get_issue_info(url)108 except (IndexError, KeyError) as error:109 return "## Invalid Github Issue URL.\n ## See examples below for reference."110 111 try:112 chain = init_chain(openai_api_key)113 summary = get_summary(context, chain)114 print(summary)115 return template_output.format(summary=summary, context=context)116 except (ValueError, openai.AuthenticationError) as error:117 return "## Invalid OpenAI API key provided."118 119html = """120<h1 style='text-align: center;'>GitHub Issue Summarizer</h1>121<img src="https://octodex.github.com/images/Professortocat_v2.png" width=100 height=100 style="display: block; margin: 0 auto;">122 """.strip()123 124examples = [125 [None, "https://github.com/rust-lang/rust/issues/97362"],126 [None, "https://github.com/rust-lang/rust/issues/83788"],127 [None, "https://github.com/langchain-ai/langchain/issues/9733"],128 [None, "https://github.com/huggingface/transformers/issues/25720"]129]130 131with gr.Blocks() as demo:132 with gr.Row():133 gr.HTML(html)134 135 with gr.Row():136 with gr.Column():137 with gr.Row():138 textbox_api_key = components.Textbox(placeholder="sk-...", label="OpenAI API Key", value=None, type="password")139 with gr.Row():140 textbox = gr.Textbox(label="Type a GitHub Issue URL:", placeholder="https://github.com/rust-lang/rust/issues/97362", lines=1)141 with gr.Row():142 summarize = gr.Button("Summarize", variant="primary")143 clear_button = gr.ClearButton()144 with gr.Row():145 gr.Examples(examples=examples, inputs=[textbox_api_key, textbox])146 with gr.Column(scale=1, min_width=1000):147 summary = gr.Markdown(value="Summary")148 summarize.click(run_all, [textbox_api_key, textbox], outputs=summary)149 clear_button.click(fn=lambda: [None, None, "Summary"], outputs=[textbox_api_key, textbox, summary])150 151demo.launch()