[clang-tools-extra] [llvm] [clang-tools-extra] Add clang-omp-pr-desc wrapper for OpenMP PR summarization (PR #144935)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 19 11:05:16 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Aviral Singh (aviralsingh2004)
<details>
<summary>Changes</summary>
This patch introduces a new Clang-compatible wrapper tool `clang-omp-pr-desc`,
which forwards arguments to `omp-pr-summary describe`. This tool simplifies
generation of structured OpenMP pull request summaries.
It is intended to be used as part of Clang tooling for OpenMP-related development workflows.
Usage:
clang-omp-pr-desc <PR_NUMBER> [--spec-path <path>]


---
Full diff: https://github.com/llvm/llvm-project/pull/144935.diff
4 Files Affected:
- (added) CLI_CLANG_TOOL3.py (+153)
- (added) clang-tools-extra/clang-omp-pr-desc/CMakeLists.txt (+3)
- (added) clang-tools-extra/clang-omp-pr-desc/ClangOMPPRDesc.cpp (+21)
- (added) setup.py (+21)
``````````diff
diff --git a/CLI_CLANG_TOOL3.py b/CLI_CLANG_TOOL3.py
new file mode 100644
index 0000000000000..1e3833f9fdf2c
--- /dev/null
+++ b/CLI_CLANG_TOOL3.py
@@ -0,0 +1,153 @@
+# CLI_CLANG_TOOL2.py
+
+import typer
+import requests
+import os
+import torch
+import numpy as np
+from sentence_transformers import SentenceTransformer
+import faiss
+from pathlib import Path
+from typing import List
+
+app = typer.Typer()
+
+# ------------------ CONFIG ------------------
+GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
+GROQ_API_KEY = os.getenv("GROQ_API_KEY")
+HEADERS = {"Authorization": f"token {GITHUB_TOKEN}"}
+REPO = "llvm/llvm-project"
+MODEL = SentenceTransformer("all-MiniLM-L6-v2")
+
+# ------------------ UTILS ------------------
+def fetch_pr_diff(pr_number: int) -> str:
+ url = f"https://api.github.com/repos/{REPO}/pulls/{pr_number}"
+ diff_url = requests.get(url, headers=HEADERS).json().get("diff_url")
+ diff = requests.get(diff_url, headers=HEADERS).text
+ return diff
+
+def fetch_pr_title(pr_number: int) -> str:
+ url = f"https://api.github.com/repos/{REPO}/pulls/{pr_number}"
+ return requests.get(url, headers=HEADERS).json().get("title", "")
+
+def load_spec_sections(path: str) -> List[str]:
+ return Path(path).read_text(encoding="utf-8").split("\n\n")
+
+def index_spec(sections: List[str]):
+ embeddings = MODEL.encode(sections)
+ index = faiss.IndexFlatL2(embeddings.shape[1])
+ index.add(np.array(embeddings))
+ return index, embeddings, sections
+
+def retrieve_spec(query: str, index, sections, embeddings, k=3):
+ q_emb = MODEL.encode([query])
+ D, I = index.search(np.array(q_emb), k)
+ return [sections[i] for i in I[0]]
+
+def extract_openmp_pragmas_from_diff(diff: str) -> List[str]:
+ return [line.strip() for line in diff.splitlines() if "#pragma omp" in line]
+
+def build_prompt(diff: str, spec_snippets: List[str], pragmas: List[str] = []):
+ prompt = f"""
+You are an assistant summarizing OpenMP Pull Requests. Given the code diff and relevant sections of the OpenMP specification, write a structured summary for the PR.
+
+## Diff:
+{diff}
+
+## Relevant Spec Sections:
+{''.join(spec_snippets)}
+
+## OpenMP Directives Detected:
+{''.join(pragmas)}
+
+## Summary:
+"""
+ return prompt
+
+def generate_summary(prompt):
+ response = requests.post(
+ "https://api.groq.com/openai/v1/chat/completions",
+ headers={
+ "Authorization": f"Bearer {GROQ_API_KEY}",
+ "Content-Type": "application/json"
+ },
+ json={
+ "model": "llama3-70b-8192",
+ "messages": [
+ {"role": "system", "content": "You are a helpful assistant for code reviewers."},
+ {"role": "user", "content": prompt},
+ ]
+ }
+ )
+ response.raise_for_status()
+ return response.json()['choices'][0]['message']['content'].strip()
+
+SECTION_LINKS = {
+ "parallel": "https://www.openmp.org/spec-html/6.0/openmpsu35.html",
+ "worksharing": "https://www.openmp.org/spec-html/6.0/openmpsu46.html",
+}
+
+def build_markdown_output(summary_text: str, spec_snippets: List[str]) -> str:
+ linked_snippets = []
+ for snippet in spec_snippets:
+ for title, url in SECTION_LINKS.items():
+ if title.lower() in snippet.lower():
+ snippet += f"\n\nš [Spec Link]({url})"
+ break
+ linked_snippets.append(snippet)
+
+ return f"""## š Pull Request Summary
+
+{summary_text}
+
+---
+
+## š Related OpenMP Spec Sections
+{''.join(f"```text\n{snippet}\n```\n\n" for snippet in linked_snippets)}"""
+
+# ------------------ COMMANDS ------------------
+ at app.command()
+def describe(pr_number: int, spec_path: str = r"D:\Web Development\CD_LAB\openmp_6_0_sections.txt"):
+ """Generate structured PR summary from GitHub PR number."""
+ title = fetch_pr_title(pr_number)
+ diff = fetch_pr_diff(pr_number)
+ sections = load_spec_sections(spec_path)
+ index, emb, sec = index_spec(sections)
+
+ snippets = retrieve_spec(title, index, sec, emb)
+ pragmas = extract_openmp_pragmas_from_diff(diff)
+ prompt = build_prompt(diff, snippets, pragmas)
+ summary = generate_summary(prompt)
+
+ print("\n\n## Generated Markdown PR Description\n")
+ print(build_markdown_output(summary, snippets))
+
+ at app.command()
+def local(diff_path: str, query: str, spec_path: str = r"D:\Web Development\CD_LAB\openmp_6_0_sections.txt"):
+ """Generate summary from a local diff file and query string."""
+ diff = Path(diff_path).read_text()
+ sections = load_spec_sections(spec_path)
+ index, emb, sec = index_spec(sections)
+
+ snippets = retrieve_spec(query, index, sec, emb)
+ pragmas = extract_openmp_pragmas_from_diff(diff)
+ prompt = build_prompt(diff, snippets, pragmas)
+ summary = generate_summary(prompt)
+
+ print("\n\n## Generated Markdown PR Description\n")
+ print(build_markdown_output(summary, snippets))
+
+# ------------------ MAIN ------------------
+if __name__ == "__main__":
+ app()
+
+# Package Installation Guide:
+# 1. Create setup.py or pyproject.toml
+# 2. Add console_scripts:
+# entry_points={
+# 'console_scripts': [
+# 'omp-pr-summary = CLI_CLANG_TOOL2:app',
+# ],
+# }
+# 3. Run: pip install -e .
+# 4. Use as: omp-pr-summary describe 144229
\ No newline at end of file
diff --git a/clang-tools-extra/clang-omp-pr-desc/CMakeLists.txt b/clang-tools-extra/clang-omp-pr-desc/CMakeLists.txt
new file mode 100644
index 0000000000000..259c96505f10a
--- /dev/null
+++ b/clang-tools-extra/clang-omp-pr-desc/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_tool(clang-omp-pr-desc
+ ClangOMPPRDesc.cpp
+)
diff --git a/clang-tools-extra/clang-omp-pr-desc/ClangOMPPRDesc.cpp b/clang-tools-extra/clang-omp-pr-desc/ClangOMPPRDesc.cpp
new file mode 100644
index 0000000000000..4e1286e2232a3
--- /dev/null
+++ b/clang-tools-extra/clang-omp-pr-desc/ClangOMPPRDesc.cpp
@@ -0,0 +1,21 @@
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ std::cerr << "Usage: clang-omp-pr-desc <PR_NUMBER> [--spec-path <path>]\n";
+ return 1;
+ }
+
+ // Reconstruct command string
+ std::ostringstream command;
+ command << "omp-pr-summary describe";
+
+ for (int i = 1; i < argc; ++i) {
+ command << " \"" << argv[i] << "\""; // quote to preserve spaces in paths
+ }
+
+ int result = std::system(command.str().c_str());
+ return result;
+}
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000..ca8f73a34c76f
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+from setuptools import setup
+
+setup(
+ name="omp-pr-summary",
+ version="0.1",
+ py_modules=["CLI_CLANG_TOOL3"],
+ install_requires=[
+ "typer[all]",
+ "requests",
+ "faiss-cpu",
+ "sentence-transformers",
+ "openai",
+ "torch",
+ "numpy"
+ ],
+ entry_points={
+ "console_scripts": [
+ "omp-pr-summary=CLI_CLANG_TOOL3:app",
+ ],
+ },
+)
``````````
</details>
https://github.com/llvm/llvm-project/pull/144935
More information about the llvm-commits
mailing list