Skip to content

Commit 37c3541

Browse files
author
sunminghui
committed
重构review class
1 parent 229927c commit 37c3541

File tree

6 files changed

+80
-110
lines changed

6 files changed

+80
-110
lines changed

api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from biz.gitlab.webhook_handler import MergeRequestHandler, PushHandler
1919
from biz.service.review_service import ReviewService
2020
from biz.utils.code_reviewer import CodeReviewer
21-
from biz.utils.im import im_notifier
21+
from biz.utils.im import notifier
2222
from biz.utils.log import logger
2323
from biz.utils.reporter import Reporter
2424

@@ -61,7 +61,7 @@ def daily_report():
6161
# 生成日报内容
6262
report_txt = Reporter().generate_report(json.dumps(commits))
6363
# 发送钉钉通知
64-
im_notifier.send_notification(content=report_txt, msg_type="markdown", title="代码提交日报")
64+
notifier.send_notification(content=report_txt, msg_type="markdown", title="代码提交日报")
6565

6666
# 返回生成的日报内容
6767
return json.dumps(report_txt, ensure_ascii=False, indent=4)
@@ -221,7 +221,7 @@ def __handle_push_event(webhook_data: dict, gitlab_token: str, gitlab_url: str):
221221

222222
except Exception as e:
223223
error_message = f'服务出现未知错误: {str(e)}\n{traceback.format_exc()}'
224-
im_notifier.send_notification(content=error_message)
224+
notifier.send_notification(content=error_message)
225225
logger.error('出现未知错误: %s', error_message)
226226

227227

@@ -285,7 +285,7 @@ def __handle_merge_request_event(webhook_data: dict, gitlab_token: str, gitlab_u
285285

286286
except Exception as e:
287287
error_message = f'AI Code Review 服务出现未知错误: {str(e)}\n{traceback.format_exc()}'
288-
im_notifier.send_notification(content=error_message)
288+
notifier.send_notification(content=error_message)
289289
logger.error('出现未知错误: %s', error_message)
290290

291291

biz/cmd/review.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from dotenv import load_dotenv
55
from pathspec import PathSpec, GitIgnorePattern
66

7-
from biz.utils.codebase_reviewer import CodeBaseReviewer
7+
from biz.utils.code_reviewer import CodeBaseReviewer
88
from biz.utils.dir_util import get_directory_tree
99
from biz.utils.log import logger
1010
from biz.utils.token_util import count_tokens, truncate_text_by_tokens

biz/event/event_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from biz.entity.review_entity import MergeRequestReviewEntity, PushReviewEntity
44
from biz.service.review_service import ReviewService
5-
from biz.utils.im import im_notifier
5+
from biz.utils.im import notifier
66

77
# 定义全局事件管理器(事件信号)
88
event_manager = {
@@ -31,7 +31,7 @@ def on_merge_request_reviewed(mr_review_entity: MergeRequestReviewEntity):
3131
3232
{mr_review_entity.review_result}
3333
"""
34-
im_notifier.send_notification(content=im_msg, msg_type='markdown', title='Merge Request Review',
34+
notifier.send_notification(content=im_msg, msg_type='markdown', title='Merge Request Review',
3535
project_name=mr_review_entity.project_name,
3636
gitlab_url_slug=mr_review_entity.gitlab_url_slug)
3737

@@ -58,7 +58,7 @@ def on_push_reviewed(entity: PushReviewEntity):
5858

5959
if entity.review_result:
6060
im_msg += f"#### AI Review 结果: \n {entity.review_result}\n\n"
61-
im_notifier.send_notification(content=im_msg, msg_type='markdown',
61+
notifier.send_notification(content=im_msg, msg_type='markdown',
6262
title=f"{entity.project_name} Push Event", project_name=entity.project_name,
6363
gitlab_url_slug=entity.gitlab_url_slug)
6464

biz/utils/code_reviewer.py

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,97 @@
11
import re
2-
32
import yaml
3+
import abc
4+
from typing import Dict, Any, List
45

56
from biz.utils.log import logger
67
from biz.llm.factory import Factory
78

89

9-
class CodeReviewer:
10-
def __init__(self):
10+
class BaseReviewer(abc.ABC):
11+
"""代码审查基类"""
12+
13+
def __init__(self, prompt_key: str):
1114
self.client = Factory().getClient()
12-
self.prompts = self._load_prompts()
15+
self.prompts = self._load_prompts(prompt_key)
1316

14-
def _load_prompts(self) -> dict:
17+
def _load_prompts(self, prompt_key: str) -> Dict[str, Any]:
1518
"""加载提示词配置"""
1619
prompt_templates_file = "conf/prompt_templates.yml"
17-
with open(prompt_templates_file, "r") as file:
18-
prompt_templates = yaml.safe_load(file)
19-
system_prompt = prompt_templates['code_review_prompt']['system_prompt']
20-
user_prompt = prompt_templates['code_review_prompt']['user_prompt']
21-
22-
if not system_prompt or not user_prompt:
23-
logger.warning(f"未找到提示词配置{prompt_templates_file}")
24-
# 抛出异常
25-
raise Exception(f"未找到提示词配置{prompt_templates_file},或配置格式不正确")
26-
27-
return {
28-
"code_review": {
29-
"system_message": {
30-
"role": "system",
31-
"content": system_prompt
32-
},
33-
"user_message": {
34-
"role": "user",
35-
"content": user_prompt
20+
try:
21+
with open(prompt_templates_file, "r") as file:
22+
prompts = yaml.safe_load(file).get(prompt_key, {})
23+
system_prompt = prompts.get("system_prompt")
24+
user_prompt = prompts.get("user_prompt")
25+
26+
if not system_prompt or not user_prompt:
27+
raise ValueError(f"提示词配置 `{prompt_key}` 为空或格式不正确")
28+
29+
return {
30+
"system_message": {"role": "system", "content": system_prompt},
31+
"user_message": {"role": "user", "content": user_prompt},
3632
}
37-
}
38-
}
33+
except (FileNotFoundError, KeyError, yaml.YAMLError) as e:
34+
logger.error(f"加载提示词配置失败: {e}")
35+
raise Exception(f"提示词配置加载失败: {e}")
36+
37+
def call_llm(self, messages: List[Dict[str, Any]]) -> str:
38+
"""调用 LLM 进行代码审核"""
39+
logger.info(f"向 AI 发送代码 Review 请求, messages: {messages}")
40+
review_result = self.client.completions(messages=messages)
41+
logger.info(f"收到 AI 返回结果: {review_result}")
42+
return review_result
43+
44+
@abc.abstractmethod
45+
def review_code(self, *args, **kwargs) -> str:
46+
"""抽象方法,子类必须实现"""
47+
pass
48+
49+
50+
class CodeReviewer(BaseReviewer):
51+
"""代码 Diff 级别的审查"""
52+
53+
def __init__(self):
54+
super().__init__("code_review_prompt")
3955

4056
def review_code(self, diffs_text: str, commits_text: str = "") -> str:
41-
"""Review代码,并返回结果"""
42-
prompts = self.prompts["code_review"]
57+
"""Review 代码并返回结果"""
4358
messages = [
44-
prompts["system_message"],
59+
self.prompts["system_message"],
4560
{
4661
"role": "user",
47-
"content": prompts["user_message"]["content"].format(
62+
"content": self.prompts["user_message"]["content"].format(
4863
diffs_text=diffs_text,
4964
commits_text=commits_text
50-
)
51-
}
65+
),
66+
},
5267
]
5368
return self.call_llm(messages)
5469

55-
def call_llm(self, messages: list) -> str:
56-
logger.info(f"向AI发送代码Review请求, message:{messages})")
57-
review_result = self.client.completions(
58-
messages=messages
59-
)
60-
logger.info(f"收到AI返回结果:{review_result}")
61-
return review_result
62-
6370
@staticmethod
6471
def parse_review_score(review_text: str) -> int:
65-
"""解析AI返回的Review结果,返回评分"""
72+
"""解析 AI 返回的 Review 结果,返回评分"""
6673
if not review_text:
67-
return 0 # 如果review_text为空,返回 0
74+
return 0
6875
match = re.search(r"总分[::]\s*(\d+)分?", review_text)
76+
return int(match.group(1)) if match else 0
77+
78+
79+
class CodeBaseReviewer(BaseReviewer):
80+
"""代码库级别的审查"""
81+
82+
def __init__(self):
83+
super().__init__("codebase_review_prompt")
6984

70-
if match:
71-
return int(match.group(1)) # 提取数值部分并转换为整数
72-
return 0 # 如果未匹配到,返回 0
85+
def review_code(self, language: str, directory_structure: str) -> str:
86+
"""Review 代码库并返回结果"""
87+
messages = [
88+
self.prompts["system_message"],
89+
{
90+
"role": "user",
91+
"content": self.prompts["user_message"]["content"].format(
92+
language=language,
93+
directory_structure=directory_structure,
94+
),
95+
},
96+
]
97+
return self.call_llm(messages)

biz/utils/codebase_reviewer.py

Lines changed: 0 additions & 55 deletions
This file was deleted.

biz/utils/im/im_notifier.py renamed to biz/utils/im/notifier.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def send_notification(content, msg_type='text', title="通知", is_at_all=False,
1313
:param gitlab_url_slug: 由gitlab服务器的url地址(如:http://www.gitlab.com)转换成的slug格式,如: www_gitlab_com
1414
"""
1515
# 钉钉推送
16-
notifier = DingTalkNotifier()
17-
notifier.send_message(content=content, msg_type=msg_type, title=title, is_at_all=is_at_all,
16+
dingtalk_notifier = DingTalkNotifier()
17+
dingtalk_notifier.send_message(content=content, msg_type=msg_type, title=title, is_at_all=is_at_all,
1818
project_name=project_name, gitlab_url_slug=gitlab_url_slug)
1919

2020
# 企业微信推送

0 commit comments

Comments
 (0)