This commit is contained in:
张建平 2025-04-24 17:38:06 +08:00
parent 451a6d8b42
commit 4277547e19
2 changed files with 40 additions and 9 deletions

View File

@ -4,6 +4,7 @@ system="""你是 PR-Reviewer, 一个专注于 Pull Request (PR) 代码分析和
diff, ( '+' ), bug , . diff, ( '+' ), bug , .
{%- else %} {%- else %}
diff, ( '+' ), bug . diff, ( '+' ), bug .
使.
{%- endif %} {%- endif %}
PR : PR :
@ -73,6 +74,7 @@ __new hunk__
(): ():
====== ======
使.
{{ extra_instructions }} {{ extra_instructions }}
使,使! 使,使!
====== ======
@ -85,6 +87,7 @@ class CodeSuggestion(BaseModel):
relevant_file: str = Field(description="相关文件的完整路径") relevant_file: str = Field(description="相关文件的完整路径")
language: str = Field(description="相关文件使用的编程语言") language: str = Field(description="相关文件使用的编程语言")
suggestion_content: str = Field(description="一个可操作的建议,用于增强、改进或修复PR中引入的新代码. 不要在这里呈现实际的代码片段, 只需要建议. 简明扼要") suggestion_content: str = Field(description="一个可操作的建议,用于增强、改进或修复PR中引入的新代码. 不要在这里呈现实际的代码片段, 只需要建议. 简明扼要")
test_content: str = Field(description="请用面向测试人员、非技术化的语言,描述本次变更对功能、流程、接口、页面等的影响,指出需要重点验证的功能点、场景或风险。不要出现任何代码术语或实现细节,让测试能直接据此设计用例或关注点。")
existing_code: str = Field(description="一个简短的代码片段, 来自PR更改后的 '__new hunk__' 部分, 该建议旨在增强或修复. 仅包括完整的代码行. 如果需要, 使用省略号 (...) 来保持简洁. 此片段应代表目标改进的特定PR代码.") existing_code: str = Field(description="一个简短的代码片段, 来自PR更改后的 '__new hunk__' 部分, 该建议旨在增强或修复. 仅包括完整的代码行. 如果需要, 使用省略号 (...) 来保持简洁. 此片段应代表目标改进的特定PR代码.")
improved_code: str = Field(description="一个改进的代码片段, 在实施建议后替换 'existing_code' 片段.") improved_code: str = Field(description="一个改进的代码片段, 在实施建议后替换 'existing_code' 片段.")
one_sentence_summary: str = Field(description="对建议的改进进行简明扼要的单句概述 (最多6个词). 关注 'what'. 保持通用性, 避免方法或变量名称,回答尽量使用简体中文,并且必须使用英文标点符号.") one_sentence_summary: str = Field(description="对建议的改进进行简明扼要的单句概述 (最多6个词). 关注 'what'. 保持通用性, 避免方法或变量名称,回答尽量使用简体中文,并且必须使用英文标点符号.")
@ -109,6 +112,8 @@ code_suggestions:
python python
suggestion_content: | suggestion_content: |
... ...
test_content: |
...
existing_code: | existing_code: |
... ...
improved_code: | improved_code: |
@ -148,6 +153,8 @@ code_suggestions:
python python
suggestion_content: | suggestion_content: |
... ...
test_content: |
...
existing_code: | existing_code: |
... ...
improved_code: | improved_code: |

View File

@ -690,10 +690,10 @@ class PRCodeSuggestions:
one_sentence_summary_list = [] one_sentence_summary_list = []
for i, suggestion in enumerate(data['code_suggestions']): for i, suggestion in enumerate(data['code_suggestions']):
try: try:
needed_keys = ['one_sentence_summary', 'label', 'relevant_file'] needed_keys = ['one_sentence_summary', 'label', 'relevant_file', 'test_content']
is_valid_keys = True is_valid_keys = True
for key in needed_keys: for key in needed_keys:
if key not in suggestion: if key not in suggestion or not suggestion[key]:
is_valid_keys = False is_valid_keys = False
get_logger().debug( get_logger().debug(
f"Skipping suggestion {i + 1}, because it does not contain '{key}':\n'{suggestion}" f"Skipping suggestion {i + 1}, because it does not contain '{key}':\n'{suggestion}"
@ -776,17 +776,23 @@ class PRCodeSuggestions:
relevant_file, relevant_lines_start, new_code_snippet relevant_file, relevant_lines_start, new_code_snippet
) )
# 增加 test_content 到 suggestion body
test_content = d.get('test_content', '').strip()
test_content_str = f"\n\n**测试建议:** {test_content}" if test_content else ""
if d.get('score'): if d.get('score'):
body = ( body = (
f"**Suggestion:** {content} [{label}, importance: {d.get('score')}]\n```suggestion\n" f"**Suggestion:** {content} [{label}, importance: {d.get('score')}]\n```suggestion\n"
+ new_code_snippet + new_code_snippet
+ "\n```" + "\n```"
+ test_content_str
) )
else: else:
body = ( body = (
f"**Suggestion:** {content} [{label}]\n```suggestion\n" f"**Suggestion:** {content} [{label}]\n```suggestion\n"
+ new_code_snippet + new_code_snippet
+ "\n```" + "\n```"
+ test_content_str
) )
code_suggestions.append( code_suggestions.append(
{ {
@ -999,7 +1005,7 @@ class PRCodeSuggestions:
header = f"建议" header = f"建议"
delta = 66 delta = 66
header += "  " * delta header += "  " * delta
pr_body += f"""<thead><tr><td><strong>类别</strong></td><td align=left><strong>{header}</strong></td><td align=center><strong>影响</strong></td></tr>""" pr_body += f"""<thead><tr><td><strong>类别</strong></td><td align=left><strong>{header}</strong></td><td align=left><strong>测试建议</strong></td><td align=center><strong>影响</strong></td></tr>"""
pr_body += """<tbody>""" pr_body += """<tbody>"""
suggestions_labels = dict() suggestions_labels = dict()
# add all suggestions related to each label # add all suggestions related to each label
@ -1013,14 +1019,14 @@ class PRCodeSuggestions:
suggestions_labels = dict( suggestions_labels = dict(
sorted( sorted(
suggestions_labels.items(), suggestions_labels.items(),
key=lambda x: max([s['score'] for s in x[1]]), key=lambda x: max([s.get('score', 0) for s in x[1]]),
reverse=True, reverse=True,
) )
) )
# sort the suggestions inside each label group by score # sort the suggestions inside each label group by score
for label, suggestions in suggestions_labels.items(): for label, suggestions in suggestions_labels.items():
suggestions_labels[label] = sorted( suggestions_labels[label] = sorted(
suggestions, key=lambda x: x['score'], reverse=True suggestions, key=lambda x: x.get('score', 0), reverse=True
) )
counter_suggestions = 0 counter_suggestions = 0
@ -1068,9 +1074,9 @@ class PRCodeSuggestions:
pr_body += f"""<td>\n\n""" pr_body += f"""<td>\n\n"""
else: else:
pr_body += f"""<tr><td>\n\n""" pr_body += f"""<tr><td>\n\n"""
suggestion_summary = ( # 新增测试建议表格列
suggestion['one_sentence_summary'].strip().rstrip('.') test_content = suggestion.get('test_content', '').strip()
) suggestion_summary = suggestion.get('one_sentence_summary', '').strip().rstrip('.')
if "'<" in suggestion_summary and ">'" in suggestion_summary: if "'<" in suggestion_summary and ">'" in suggestion_summary:
# escape the '<' and '>' characters, otherwise they are interpreted as html tags # escape the '<' and '>' characters, otherwise they are interpreted as html tags
get_logger().info( get_logger().info(
@ -1085,6 +1091,8 @@ class PRCodeSuggestions:
pr_body += f""" pr_body += f"""
**{suggestion_content}** **{suggestion_content}**
**测试建议** {suggestion.get('test_content', '').strip()}
[{relevant_file} {range_str}]({code_snippet_link}) [{relevant_file} {range_str}]({code_snippet_link})
{example_code.rstrip()} {example_code.rstrip()}
@ -1096,12 +1104,15 @@ class PRCodeSuggestions:
pr_body += f"</details>" pr_body += f"</details>"
# 新增测试建议表格列
pr_body += f"</td><td>{test_content}</td>"
# # add another column for 'score' # # add another column for 'score'
score_int = int(suggestion.get('score', 0)) score_int = int(suggestion.get('score', 0))
score_str = f"{score_int}" score_str = f"{score_int}"
if get_settings().pr_code_suggestions.new_score_mechanism: if get_settings().pr_code_suggestions.new_score_mechanism:
score_str = self.get_score_str(score_int) score_str = self.get_score_str(score_int)
pr_body += f"</td><td align=center>{score_str}\n\n" pr_body += f"<td align=center>{score_str}\n\n"
pr_body += f"</td></tr>" pr_body += f"</td></tr>"
counter_suggestions += 1 counter_suggestions += 1
@ -1109,6 +1120,19 @@ class PRCodeSuggestions:
# pr_body += "</details>" # pr_body += "</details>"
# pr_body += """</td></tr>""" # pr_body += """</td></tr>"""
pr_body += """</tr></tbody></table>""" pr_body += """</tr></tbody></table>"""
# 额外输出测试建议列表
test_suggestions = [
s.get('test_content', '').strip()
for label in suggestions_labels.values()
for s in label
if s.get('test_content', '').strip()
]
if test_suggestions:
pr_body += "\n\n<strong>【测试建议汇总】</strong><br>\n"
for idx, test_content in enumerate(test_suggestions, 1):
pr_body += f"{idx}. {test_content}<br>\n"
return pr_body return pr_body
except Exception as e: except Exception as e:
get_logger().info( get_logger().info(