Skip to content

Commit ec53ab8

Browse files
committed
Update prreview patchflow
1 parent 2c33f7e commit ec53ab8

File tree

3 files changed

+479
-464
lines changed

3 files changed

+479
-464
lines changed

patchwork/patchflows/PRReview/PRReview.py

Lines changed: 103 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,13 @@
1313
ExtractModelResponse,
1414
PreparePR,
1515
PreparePrompt,
16-
ReadPRDiffs,
16+
ReadPRDiffs, SimplifiedLLMOnce, JoinList,
1717
)
1818

1919
_DEFAULT_PROMPT_JSON = Path(__file__).parent / "pr_review_prompt.json"
2020
_DEFAULT_INPUT_FILE = Path(__file__).parent / "defaults.yml"
2121

2222

23-
_NONE = "none"
24-
_SHORT = "short"
25-
_LONG = "long"
26-
_SUMMARY_LEVEL = {
27-
_NONE: 0,
28-
_SHORT: 1,
29-
_LONG: 2,
30-
}
31-
32-
3323
class PRReview(Step):
3424
def __init__(self, inputs: dict):
3525
PatchflowProgressBar(self).register_steps(
@@ -43,16 +33,6 @@ def __init__(self, inputs: dict):
4333
final_inputs = yaml.safe_load(_DEFAULT_INPUT_FILE.read_text())
4434
final_inputs.update(inputs)
4535

46-
if "prompt_template_file" not in final_inputs.keys():
47-
final_inputs["prompt_template_file"] = _DEFAULT_PROMPT_JSON
48-
49-
diff_summary = final_inputs.get("diff_summary", _LONG)
50-
if diff_summary.lower() not in _SUMMARY_LEVEL.keys():
51-
raise ValueError(f"Invalid diff_summary, accepted diff_summary values: {_SUMMARY_LEVEL.keys()}")
52-
self.verbosity = _SUMMARY_LEVEL[diff_summary.lower()]
53-
54-
self.is_suggestion_required = bool(final_inputs.get("diff_suggestion"))
55-
5636
validate_steps_with_inputs(
5737
set(final_inputs.keys()).union(
5838
{
@@ -71,54 +51,105 @@ def __init__(self, inputs: dict):
7151
self.inputs = final_inputs
7252

7353
def run(self) -> dict:
74-
if self.verbosity == _SUMMARY_LEVEL[_NONE]:
75-
return dict()
76-
77-
outputs = ReadPRDiffs(self.inputs).run()
78-
self.inputs["prompt_values"] = outputs["diffs"]
79-
80-
outputs = LLM(
81-
dict(
82-
prompt_id="diffreview-suggestion" if self.is_suggestion_required else "diffreview",
83-
model_response_format=dict(type="json_object"),
84-
**self.inputs,
85-
)
86-
).run()
87-
self.inputs.update(outputs)
88-
89-
summaries = []
90-
for raw_response, prompt_values in zip(self.inputs["openai_responses"], self.inputs["prompt_values"]):
91-
response = json.loads(raw_response)
92-
summary = {}
93-
if "path" in prompt_values.keys():
94-
summary["path"] = prompt_values["path"]
95-
if "review" in response.keys():
96-
summary["commit_message"] = response["review"]
97-
if "suggestion" in response.keys():
98-
summary["patch_message"] = response["suggestion"]
99-
summaries.append(summary)
100-
101-
header = ""
102-
if self.verbosity > _SUMMARY_LEVEL[_SHORT]:
103-
filtered_summaries = [
104-
str(summary["commit_message"]) for summary in summaries if summary.get("commit_message")
105-
]
106-
self.inputs["prompt_id"] = "diffreview_summary"
107-
self.inputs["prompt_values"] = [{"diffreviews": "\n".join(filtered_summaries)}]
108-
109-
outputs = PreparePrompt(self.inputs).run()
110-
self.inputs.update(outputs)
111-
outputs = CallLLM(self.inputs).run()
112-
self.inputs.update(outputs)
113-
header = self.inputs["openai_responses"][0]
114-
115-
self.inputs["pr_header"] = header
116-
self.inputs["modified_code_files"] = summaries
117-
outputs = PreparePR(self.inputs).run()
118-
self.inputs.update(outputs)
119-
120-
self.inputs["pr_comment"] = self.inputs["pr_body"]
121-
outputs = CreatePRComment(self.inputs).run()
122-
self.inputs.update(outputs)
123-
124-
return self.inputs
54+
pr_diffs_outputs = ReadPRDiffs(self.inputs).run()
55+
56+
reviews = []
57+
for diffs in iter(pr_diffs_outputs["diffs"]):
58+
llm1_outputs = SimplifiedLLMOnce(
59+
dict(
60+
prompt_value=diffs,
61+
user_prompt='''\
62+
Analyze the following code diff against the provided rules:
63+
64+
<CODE_DIFF>
65+
{{diff}}
66+
</CODE_DIFF>
67+
68+
<RULES>
69+
- Do not ignore potential bugs in the code.
70+
- Do not overlook possible security vulnerabilities introduced by code modifications.
71+
- Do not deviate from the original coding standards established in the pull request.
72+
</RULES>
73+
74+
For each rule, determine if there\'s a violation. Use the following chain of thought process:
75+
76+
1. Understand the rule
77+
2. Examine the diff line by line
78+
3. Identify any potential violations
79+
4. Determine the specific line numbers of violations
80+
5. Summarize your findings
81+
82+
Rule 1:
83+
1. Rule understanding: [Briefly explain the rule]
84+
2. Diff examination: [Describe how you\'re examining the diff]
85+
3. Potential violations: [List any potential violations you\'ve identified]
86+
4. Line numbers: [If violations exist, list the specific line numbers]
87+
5. Summary: [Summarize your findings for this rule]
88+
89+
Rule 2:
90+
[Repeat the above structure for each rule]
91+
92+
Now, carefully review your reasoning in the section above. Ensure that your conclusions are consistent with the analysis you\'ve done for each rule.
93+
94+
Your review should have the following markdown format:
95+
96+
<REVIEW_FORMAT>
97+
## File Changed: `{{path}}`
98+
99+
Details: [If rule violation include brief prescriptive explanation]
100+
101+
Affected Code Snippet:
102+
[Original code enclosed in a code block from the file that is affected by this violation. If no violation, write "N/A"]
103+
104+
Start Line: [Starting Line number of the affected code. If no violation, write "N/A"]
105+
106+
End Line: [Ending Line number of the affected code. If no violation, write "N/A"]
107+
108+
-------------
109+
110+
Details: [If rule violation include brief prescriptive explanation]
111+
112+
Affected Code Snippet:
113+
[Original code enclosed in a code block from the file that is affected by this violation. If no violation, write "N/A"]
114+
115+
Start Line: [Starting Line number of the affected code. If no violation, write "N/A"]
116+
117+
End Line: [Ending Line number of the affected code. If no violation, write "N/A"]
118+
119+
-------------
120+
121+
... (continue for all rules)
122+
</REVIEW_FORMAT>
123+
124+
Ensure that you include all rules in your response, even if there\'s no violation. The output should directly reflect the reasoning in your thinking section.
125+
''',
126+
json_schema={"review": "The markdown text of the reviews"},
127+
model="claude-3-5-sonnet-latest")
128+
).run()
129+
130+
llm2_outputs = SimplifiedLLMOnce(
131+
dict(
132+
prompt_value=llm1_outputs,
133+
user_prompt='''\
134+
You are a software manager compiling code reviews from all teams. You are given a list of code reviews. You have to remove code reviews that is either not actionable or useful. Do not change the accepted reviews, return the original review for the response. Do not remove the path from the review.
135+
136+
<code_reviews>
137+
{{review}}
138+
<code_reviews>
139+
140+
You should return an empty response if there are no code reviews that is actionable or useful.
141+
''',
142+
json_schema={"review": "The reviews curated"},
143+
model="claude-3-5-sonnet-latest")
144+
).run()
145+
146+
review = llm2_outputs.get("review")
147+
if review is not None and len(str(review)) > 0:
148+
reviews.append(review)
149+
150+
if len(reviews) > 0:
151+
reviews_str = "\n".join(reviews)
152+
else:
153+
reviews_str = "No issues found."
154+
155+
return CreatePRComment(dict(pr_comment=reviews_str, **self.inputs)).run()

patchwork/steps/CallShell/CallShell.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from patchwork.common.utils.utils import mustache_render
99
from patchwork.logger import logger
1010
from patchwork.step import Step, StepStatus
11-
from patchwork.steps import CallSQL
1211
from patchwork.steps.CallShell.typed import CallShellInputs, CallShellOutputs
1312

1413

0 commit comments

Comments
 (0)