diff --git a/pr_reivew/Dockerfile b/pr_reivew/Dockerfile index 5751bbfcd53d5eefa3f4c34d51a1883233f0f98d..e21a5d9ef99b414f099fdacbcd14928678226f05 100644 --- a/pr_reivew/Dockerfile +++ b/pr_reivew/Dockerfile @@ -23,9 +23,9 @@ ENV PATH="/home/pr/python/bin:${PATH}" RUN python3 -V -WORKDIR /home/pr/pr-message +WORKDIR /home/pr/pr_review -COPY . . +COPY ./pr_review/ . RUN pip3 install --no-cache-dir -r requirements.txt diff --git a/pr_reivew/src/config/init_config.py b/pr_reivew/src/config/init_config.py index c29f1022b541e5cf6a73d45825c804aacd62db5b..6345d1db0265b52b6858deeb86799bee546b5977 100644 --- a/pr_reivew/src/config/init_config.py +++ b/pr_reivew/src/config/init_config.py @@ -17,6 +17,7 @@ def init_config(path): config["gpt"]["encoding_name"], config["gpt"]["url"], config["gpt"]["limit"], + config["gpt"]["prompt"], ) diff --git a/pr_reivew/src/gpt/bot.py b/pr_reivew/src/gpt/bot.py index 1cb89d8d29611aa72adb74288c7366e954cc4eae..1b7245cdb106789b7f5738d726a388d44f3edb7a 100644 --- a/pr_reivew/src/gpt/bot.py +++ b/pr_reivew/src/gpt/bot.py @@ -8,12 +8,14 @@ class Gpt: encoding_name = '' url = '' limit = 5 + prompt = '' - def init_config_attr(max_token_length, encoding_name, url, limit): + def init_config_attr(max_token_length, encoding_name, url, limit, prompt): Gpt.max_token_length = max_token_length Gpt.encoding_name = encoding_name Gpt.url = url Gpt.limit = limit + Gpt.prompt = prompt class Bot(Gpt): @@ -37,7 +39,7 @@ class Bot(Gpt): If there are no issues found on a line range, you MUST respond with the text `LGTM!` for that line range in the review section. - ## Example + ## Example 1 ### Example changes @@ -46,15 +48,9 @@ class Bot(Gpt): z = x / y return z - 20: def add(x, y): - 21: z = x + y - 22: retrn z - 23: - 24: def multiply(x, y): - 25: return x * y - - def subtract(x, y): - z = x - y + def add(x, y): + z = x + y + retrn z ``` ---old_hunk--- @@ -64,9 +60,6 @@ class Bot(Gpt): def add(x, y): return x + y - - def subtract(x, y): - z = x - y ``` ---comment_chains--- @@ -78,12 +71,39 @@ class Bot(Gpt): ### Example response - 22-22: 这里有语法错误 ```diff - retrn z + return z ``` + + ## Example 2 + + ### Example changes + + ---new_hunk--- + ``` + def add(x, y): + z = x + y + retrn z + ``` + + ---old_hunk--- + ``` + def add(x, y): + return x + y + ``` + + ---comment_chains--- + ``` + Please review this change. + ``` + + ---end_change_section--- + + ### Example response + + LGTM ''' @@ -91,10 +111,6 @@ class Bot(Gpt): data = { "model": "gpt-3.5-turbo", "messages": [ - { - "role": "system", - "content": self.system_message - }, { "role": "user", "content": prompt @@ -107,7 +123,7 @@ class Bot(Gpt): ) if response.status_code != 200: logger.info("get answer error") - logger.info(response.status_code) + logger.info(response.text) return response diff --git a/pr_reivew/src/review_code/options.py b/pr_reivew/src/review_code/options.py index 09823ff93883bedaef1a4fa3b74a2d64de827733..591c5927ab2f9702bb29c102eaa6d0b134be5212 100644 --- a/pr_reivew/src/review_code/options.py +++ b/pr_reivew/src/review_code/options.py @@ -6,7 +6,7 @@ class Options: self.maxFiles = 1000 self.pathFilters= '' self.TokenLimits = 1024 - self.rules = {'*.txt': False, '*.py': False, '*.md': False} + self.rules = {'*.py': False, '*.java': False, '*.js': False, '*.cpp': False,} self.debug = False def checkPath(self, path): diff --git a/pr_reivew/src/review_code/prompts.py b/pr_reivew/src/review_code/prompts.py index b41331a0c59ad843f34cf930232341b6d02e77ca..c9d9401a66dc354cc482b9de85a436999aa55329 100644 --- a/pr_reivew/src/review_code/prompts.py +++ b/pr_reivew/src/review_code/prompts.py @@ -92,21 +92,15 @@ class Prompts: $patches ''' - - self.reviewFileDiff = ''' - ## 请用中文对 `$filename` 的语法错误进行 review,并给出修改意见 - $patches - ''' - def renderSummarizeFileDiff(self, inputIn, reviewSimpleChanges): prompt = self.summarizeFileDiff if not reviewSimpleChanges: prompt += self.triageFileDiff return inputIn.render(prompt) # input对象中的具体内容填充到prompt字符串的{}中 - def renderReviewFileDiff(self, inputIn: Input): - return inputIn.render(self.reviewFileDiff) + def renderReviewFileDiff(self, inputIn: Input, prompt: str): + return inputIn.render(prompt) diff --git a/pr_reivew/src/review_code/review.py b/pr_reivew/src/review_code/review.py index f8d991e5611efeecaf9490394cf75c4075665837..b12e47d26bb9ff2e04c8bb76f8ea3cebfcddb42f 100644 --- a/pr_reivew/src/review_code/review.py +++ b/pr_reivew/src/review_code/review.py @@ -125,10 +125,10 @@ class CodeReview: fileDiff = aFile.get('patch', '') diff_lines = fileDiff.splitlines() - patches = [] diff_num = 0 for patch in self.splitPatch(aFile.get('patch', '')): + patch = patch.replace('\\ No newline at end of file', '') diff_num += 1 patchLines = self.patchStartEndLine(patch) if not patchLines: @@ -138,7 +138,7 @@ class CodeReview: continue hunksStr = '''---new_hunk---\n\'\'\'\n%s\n\'\'\'\n---old_hunk---\n\'\'\'\n%s\n\'\'\''''%(hunks.get('newHunk', None), hunks.get('oldHunk', None)) - comment_diff_line = self.get_patch_diff_line(diff_num, diff_lines) + comment_diff_line = self.get_patch_diff_line(diff_num, diff_lines, fileDiff) patches.append([patchLines.get('newHunk', None).get('startLine', None), patchLines.get('newHunk', None).get('endLine', None), hunksStr, comment_diff_line]) if len(patches) > 0: filteredFiles.append([aFile.get('filename', None), fileContent, fileDiff, patches]) @@ -156,17 +156,33 @@ class CodeReview: if lgtm_num == len(patches): self.giteeApi.submit_review(body = "/lgtm", commitId = self.commits[0], filename=filename, line=patches[-1][-1]) - def get_patch_diff_line(self, diff_num, diff_lines): + def get_patch_diff_line(self, diff_num, diff_lines, file_diff): line_no = 0 hit_no = 0 + diff_lines = self.reduce(diff_lines) for line in diff_lines: if line.startswith('@@'): - if hit_no == diff_num: + if hit_no == diff_num and self.modify_line(file_diff): + return line_no - 1 + elif hit_no == diff_num: return line_no hit_no += 1 line_no += 1 + if self.only_add_or_delate(diff_lines, '-') or self.only_add_or_delate(diff_lines, '+'): + line_no -= 1 + elif self.modify_line(file_diff): + line_no -= 1 return line_no + # 判断第一个修改行在文件中的位置 + # 如果在前四行有修改,则在gitee上不会显示 @@ -0,0 +0,0 @@ + # 则行号应该减1 + def modify_line(self, file_diff): + re_split = re.split('^@@ -(\d+),(\d+) \+(\d+),(\d+) @@', file_diff) + if len(re_split) > 1 and int(re_split[1]) == 1: + return True + return False + def splitPatch(self, patch): if not patch: return [] @@ -187,7 +203,25 @@ class CodeReview: if lastLine != -1: results.append('\n'.join(splitLines[lastLine:])) return results + + def only_add_or_delate(self, diff_lines, operator): + for file_diff in diff_lines: + if not file_diff.startswith(operator) and not file_diff.startswith('@@'): + return False + return True + + # 处理 \ No newline at end of file + def reduce(self, diff_lines): + ans = [] + line = 0 + for file_diff in diff_lines: + line += 1 + if '\\ No newline at end of file' == file_diff and line == len(diff_lines): + continue + ans.append(file_diff) + return ans + def patchStartEndLine(self, patch): reSplit = re.split('^@@ -(\d+),(\d+) \+(\d+),(\d+) @@', patch) if len(reSplit) > 1: @@ -232,7 +266,7 @@ class CodeReview: else: oldHunkLines.append(line) if removalOnly or (currentLine > skipStart and currentLine <= len(lines) - skipEnd): - newHunkLines.append(str(newLine) + ': ' + line) + newHunkLines.append(line) else: newHunkLines.append(line) newLine += 1 @@ -263,7 +297,7 @@ class CodeReview: if patchesPacked >= patchesToPack: logger.info('unable to pack more patches into this request, packed: {}, total patches: {}, skipping'.format(patchesPacked, len(patches))) if self.options.debug: - logger.info('prompt so far: {}'.format(self.prompts.renderReviewFileDiff(ins))) + logger.info('prompt so far: {}'.format(self.prompts.renderReviewFileDiff(ins, self.bot.prompt))) break patchesPacked += 1 commentChain = '' @@ -281,7 +315,8 @@ class CodeReview: if commentChain: ins.patches += '---comment_chains---\n\'\'\'{}\'\'\'---end_change_section---'.format(commentChain) if patchesPacked > 0: - messages = self.prompts.renderReviewFileDiff(ins) + messages = self.prompts.renderReviewFileDiff(ins, self.bot.prompt) + logger.info(messages) res = self.bot.chat(messages) if res.status_code != 200: