PR Agent의 Improve 기능은 AI를 활용해 풀 리퀘스트(PR)의 코드를 분석하고 개선 방안을 제시해주는 도구입니다.
/improve
명령어를 사용하면 AI가 PR 코드를 꼼꼼히 살펴보고 이런 개선점을 찾아줍니다:
Improve 기능의 핵심은 pr_agent/tools/pr_code_suggestions.py
파일에 있는 PRCodeSuggestions
클래스입니다. 이 클래스가 어떻게 작동하는지 살펴보겠습니다:
class PRCodeSuggestions:
def __init__(self, pr_url: str, ...):
# PR 정보와 설정 초기화
async def run(self):
# 1. PR 정보 수집
# 2. AI 모델로 개선 제안 생성
# 3. 제안에 대한 자체 평가
# 4. 결과 처리 및 댓글 게시
전체 과정은 이렇게 진행됩니다:
configuration.toml
파일에서 설정을 조정해 원하는 대로 개선 기능을 커스터마이징할 수 있습니다:
[pr_code_suggestions]
max_context_tokens=24000 # 최대 컨텍스트 토큰 수
commitable_code_suggestions = false # GitHub에서 바로 적용 가능한 형식으로 제안할지
focus_only_on_problems=true # 심각한 문제에만 집중할지
suggestions_score_threshold=0 # 제안 점수 기준값 (0-10)
num_code_suggestions_per_chunk=4 # 청크당 최대 제안 수
parallel_calls = true # 병렬 처리 사용
new_score_mechanism=true # 새 점수 체계 사용 (High/Medium/Low)
# 셀프 리뷰 설정
demand_code_suggestions_self_review=false # 작성자 셀프 리뷰 체크박스 추가
code_suggestions_self_review_text= "..." # 체크박스 텍스트
approve_pr_on_self_review=false # 셀프 리뷰 후 자동 승인
특히 focus_only_on_problems
옵션으로 심각한 문제만 보거나, 코드 품질 전반에 관한 제안까지 모두 받을 수 있습니다.
Improve 기능의 시스템 프롬프트를 살펴보면:
당신은 PR-Reviewer, PR 코드 분석과 제안을 전문으로 하는 AI입니다.
코드 diff를 검토하고, 새로 추가된 코드('+' 접두사가 있는 줄)에 집중해서
간결하고 실행 가능한 제안을 제공해 주세요.
특히 다음을 중점적으로 확인해 주세요:
- 잠재적 버그와 문제
- 보안 취약점
- 코드 품질과 성능 개선점
...
사용자 프롬프트에는 실제 PR 정보가 포함됩니다:
PR 정보:
제목: '새로운 로그인 기능 추가'
PR Diff:
======
## File: 'src/auth/login.js'
@@ ... @@ function login():
__new hunk__
11 const validateUser = (user) => {
12 return db.findUser(user);
13 +const processLogin = (username, password) => {
14 + const user = { name: username, pwd: password };
15 + return validateUser(user);
16 +}
...
======
이 두 프롬프트를 받은 AI는 코드를 분석하고 실용적인 개선 방안을 제안해줍니다.
큰 규모의 PR을 처리할 때 PR Agent는 몇 가지 전략을 사용합니다:
self.patches_diff_list = get_pr_multi_diffs(
self.git_provider,
self.token_handler,
model,
max_calls=get_settings().pr_code_suggestions.max_number_of_calls
)
큰 PR을 여러 조각으로 나눠서 각 부분을 따로 분석합니다.
if get_settings().pr_code_suggestions.parallel_calls:
prediction_list = await asyncio.gather(
*[self._get_prediction(model, patches_diff, patches_diff_no_line_numbers)
for patches_diff, patches_diff_no_line_numbers in zip(...)]
)
여러 코드 청크를 동시에 처리해서 속도를 높입니다.
score_threshold = max(1, int(get_settings().pr_code_suggestions.suggestions_score_threshold))
for prediction in predictions["code_suggestions"]:
score = int(prediction.get("score", 1))
if score >= score_threshold:
data["code_suggestions"].append(prediction)
중요도 점수를 기준으로 필터링해서 가장 중요한 제안에 집중할 수 있습니다.
AI의 코드 개선 방안은 YAML 구조로 만들어집니다:
code_suggestions:
- relevant_file: "src/auth/login.js"
language: "javascript"
existing_code: "const processLogin = (username, password) => {\n const user = { name: username, pwd: password };\n return validateUser(user);\n}"
suggestion_content: "비밀번호는 평문으로 저장하거나 전송하면 안 됩니다. 비밀번호를 해싱해서 사용하세요."
improved_code: "const processLogin = (username, password) => {\n const hashedPwd = hashPassword(password);\n const user = { name: username, pwd: hashedPwd };\n return validateUser(user);\n}"
one_sentence_summary: "비밀번호 해싱 추가"
label: "security"
score: 9
score_why: "보안 취약점으로, 사용자 비밀번호가 노출될 위험이 있습니다."
이 제안은 두 가지 방식으로 보여질 수 있습니다:
## PR Code Suggestions ✨
<table>
<thead><tr><td><strong>Category</strong></td><td><strong>Suggestion</strong></td><td><strong>Impact</strong></td></tr>
<tbody>
<tr>
<td>Security</td>
<td>
<details><summary>비밀번호 해싱 추가</summary>
**비밀번호는 평문으로 저장하거나 전송하면 안 됩니다. 비밀번호를 해싱해서 사용하세요.**
[src/auth/login.js [13-16]](링크)
```diff
- const processLogin = (username, password) => {
- const user = { name: username, pwd: password };
- return validateUser(user);
- }
+ const processLogin = (username, password) => {
+ const hashedPwd = hashPassword(password);
+ const user = { name: username, pwd: hashedPwd };
+ return validateUser(user);
+ }
```
</details>
</td>
<td align=center>High</td>
</tr>
</tbody>
</table>
**Suggestion:** 비밀번호는 평문으로 저장하거나 전송하면 안 됩니다. 비밀번호를 해싱해서 사용하세요. [Security, importance: 9]
```suggestion
const processLogin = (username, password) => {
const hashedPwd = hashPassword(password);
const user = { name: username, pwd: hashedPwd };
return validateUser(user);
}
response_reflect = await self.self_reflect_on_suggestions(
data["code_suggestions"],
patches_diff,
model=model_reflect_with_reasoning
)
AI가 만든 제안을 다시 한번 검토해서 품질과 중요도를 평가합니다. 이렇게 하면 제안의 정확성과 유용성이 더 높아집니다.
for suggestion in data_above_threshold['code_suggestions']:
relevant_file = suggestion['relevant_file'].strip()
relevant_lines_start = int(suggestion['relevant_lines_start'])
relevant_lines_end = int(suggestion['relevant_lines_end'])
코드를 변경해야 할 정확한 위치(파일과 라인 번호)를 자동으로 찾아줍니다.
def dedent_code(self, relevant_file, relevant_lines_start, new_code_snippet):
# 원본 코드의 들여쓰기를 유지하도록 새 코드를
제안된 코드가 원본 코드의 들여쓰기 스타일을 그대로 유지하도록 자동으로 맞춰줍니다.