PR-Agent Describe 프롬프트 분석

Tasker_Jang·2025년 4월 29일
0

PR-Agent의 /describe 명령어는 AI 모델에게 특정 형식의 프롬프트를 제공하여 풍부하고 구조화된 PR 설명을 생성하도록 합니다. 이 글에서는 이 프롬프트의 구조와 기능을 상세히 분석해 보겠습니다.

AI와의 대화: 프롬프트의 핵심 구조

PR-Agent가 AI와 소통할 때는 두 가지 주요 메시지를 보냅니다:

  1. 시스템 프롬프트: "너는 이런 일을 하는 PR-Reviewer야. 이런 방식으로 응답해줘."
  2. 사용자 프롬프트: "여기 PR 정보야. 이걸 분석해서 설명해줘."

이 프롬프트들은 pr_agent/settings/pr_description_prompts.toml 파일에 정의되어 있으며, 각각 AI의 역할과 수행할 작업을 세부적으로 안내합니다.

시스템 프롬프트: AI의 역할 정의하기

시스템 프롬프트는 AI에게 어떤 역할을 맡아야 하는지, 어떤 형식으로 응답해야 하는지 알려줍니다. 가장 먼저 AI의 정체성과 임무를 설정합니다:

You are PR-Reviewer, a language model designed to review a Git Pull Request (PR).
Your task is to provide a full description for the PR content - type, description, title and files walkthrough.

이 간단한 소개로 AI는 자신이 PR 리뷰어라는 것과 주요 임무가 PR 내용 설명임을 이해합니다.

세부 지시사항: 어디에 집중해야 할까?

다음으로 중요한 점은 AI에게 무엇에 집중해야 하는지 구체적으로 알려주는 것입니다:

- Focus on the new PR code (lines starting with '+' in the 'PR Git Diff' section).
- Keep in mind that the 'Previous title', 'Previous description' and 'Commit messages' sections may be partial, simplistic, non-informative or out of date.
- The generated title and description should prioritize the most significant changes.

이 지시사항들이 정말 중요한데요, 특히 "새로 추가된 코드에 집중하라"는 부분과 "기존 제목이나 설명은 참고만 하라"는 부분은 AI가 실제 코드 변경에 기반하여 설명을 작성하도록 유도합니다. 이전 설명이 부실하더라도 AI가 코드 자체를 분석해 정확한 설명을 만들 수 있는 이유죠!

출력 구조 정의: 형식이 중요해요

가장 흥미로운 부분은 AI에게 원하는 출력 형식을 Python의 Pydantic 모델처럼 정의하는 부분입니다:

class PRType(str, Enum):
    bug_fix = "Bug fix"
    tests = "Tests"
    enhancement = "Enhancement"
    documentation = "Documentation"
    other = "Other"

class FileDescription(BaseModel):
    filename: str = Field(description="The full file path of the relevant file")
    changes_summary: str = Field(description="concise summary of the changes in the relevant file")
    changes_title: str = Field(description="one-line summary capturing the main theme of changes")
    label: str = Field(description="a single semantic label that represents a type of code changes")

class PRDescription(BaseModel):
    type: List[PRType] = Field(description="one or more types that describe the PR content")
    description: str = Field(description="summarize the PR changes in up to four bullet points")
    title: str = Field(description="a concise and descriptive title that captures the PR's main theme")
    pr_files: List[FileDescription] = Field(description="a list of all the files that were changed")

이런 명확한 구조 정의 덕분에 AI는 정확히 어떤 정보를 어떤 형식으로 제공해야 하는지 이해하게 됩니다. 각 필드에 대한 설명까지 붙여서 AI가 각 섹션에 어떤 내용을 채워야 할지 명확히 알 수 있죠.

한 가지 중요한 점은 이 구조가 동적으로 조정될 수 있다는 것입니다:

{%- if enable_semantic_files_types %}
    pr_files: List[FileDescription] = Field(...)
{%- endif %}

이런 조건문을 통해 PR-Agent 설정에 따라 출력 형식이 달라질 수 있습니다. 예를 들어, 의미론적 파일 분류 기능을 켜거나 끄는 것에 따라 출력 형식이 조정되죠.

사용자 프롬프트: PR 데이터 제공하기

사용자 프롬프트는 AI에게 실제 PR 데이터를 제공합니다. 여기에는 여러 요소가 포함됩니다:

티켓 정보: 맥락 이해하기

{%- if related_tickets %}
Related Ticket Info:
{% for ticket in related_tickets %}
=====
Ticket Title: '{{ ticket.title }}'
...
{% endfor %}
{%- endif %}

PR과 연관된 티켓이 있다면, 이 정보를 통해 AI는 PR의 목적과 맥락을 더 잘 이해할 수 있습니다.

PR 기본 정보: 출발점 제공하기

PR Info:

Previous title: '{{title}}'

Previous description:
=====
{{ description|trim }}
=====

Branch: '{{branch}}'

Commit messages:
=====
{{ commit_messages_str|trim }}
=====

기존 PR 제목, 설명, 브랜치 이름, 커밋 메시지 등의 정보는 AI가 분석을 시작하는 기본 정보를 제공합니다. 물론 시스템 프롬프트에서 언급했듯이, 이 정보는 참고용으로만 사용됩니다.

Git Diff: 실제 코드 변경 분석하기

The PR Git Diff:
=====
{{ diff|trim }}
=====

Note that lines in the diff body are prefixed with a symbol that represents the type of change: '-' for deletions, '+' for additions, and ' ' (a space) for unchanged lines.

가장 중요한 부분은 바로 Git Diff입니다. 이것은 실제 코드 변경 내용을 담고 있으며, AI는 이를 분석하여 PR의 실제 의미를 파악합니다. AI에게 diff 라인 접두사의 의미도 설명해주어 변경 유형을 정확히 이해할 수 있게 합니다.

프롬프트의 마법: 템플릿 엔진

PR-Agent는 Jinja2 템플릿 엔진을 사용하여 프롬프트를 동적으로 생성합니다. 이는 몇 가지 멋진 기능을 가능하게 합니다:

조건부 콘텐츠

{%- if enable_semantic_files_types %}
  pr_files: List[FileDescription] = ...
{%- endif %}

설정에 따라 프롬프트 내용이 달라질 수 있습니다. 예를 들어, 의미론적 파일 분류 기능을 활성화했는지에 따라 관련 섹션을 포함하거나 제외할 수 있죠.

변수 삽입

Previous title: '{{title}}'

실제 PR 데이터(제목, 설명, diff 등)를 프롬프트에 동적으로 삽입할 수 있습니다.

반복 처리

{% for ticket in related_tickets %}
  Ticket Title: '{{ ticket.title }}'
  ...
{% endfor %}

여러 항목(티켓, 파일 등)을 반복적으로 처리할 수 있습니다.

대규모 PR 처리: 분할 정복 전략

대규모 PR을 처리할 때는 특별한 접근 방식이 필요합니다. PR-Agent는 이를 위해 두 개의 특수 프롬프트를 사용합니다:

  1. 파일 전용 프롬프트: 변경된 파일 목록과 각 파일의 변경 내용만 분석

    # pr_description_only_files_prompts
  2. 설명 전용 프롬프트: PR 전체에 대한 제목, 유형, 설명만 생성

    # pr_description_only_description_prompts

이렇게 큰 PR을 작은 조각으로 나누어 처리하면 AI의 토큰 제한을 효과적으로 관리하면서도 전체 PR을 포괄적으로 분석할 수 있습니다.

if not get_settings().pr_description.async_ai_calls:
    # 동기 처리 (순차적)
    for patches in patches_compressed_list:
        # 각 청크 처리
else:  # 비동기 처리 (병렬)
    tasks = []
    for patches in patches_compressed_list:
        # 모든 청크를 동시에 처리
    results = await asyncio.gather(*tasks)

비동기 처리를 활성화하면 여러 청크를 병렬로 처리하여 대규모 PR도 빠르게 분석할 수 있습니다.

프롬프트 적용 과정: 코드로 보기

실제로 프롬프트가 어떻게 적용되는지 코드 레벨에서 살펴봅시다:

async def _get_prediction(self, model: str, patches_diff: str, prompt="pr_description_prompt") -> str:
    # 변수 준비
    variables = copy.deepcopy(self.vars)
    variables["diff"] = patches_diff
    
    # Jinja2 환경 설정
    environment = Environment(undefined=StrictUndefined)
    
    # 프롬프트 렌더링
    system_prompt = environment.from_string(get_settings().get(prompt, {}).get("system", "")).render(variables)
    user_prompt = environment.from_string(get_settings().get(prompt, {}).get("user", "")).render(variables)
    
    # AI 모델 호출
    response, finish_reason = await self.ai_handler.chat_completion(
        model=model,
        temperature=get_settings().config.temperature,
        system=system_prompt,
        user=user_prompt
    )
    
    return response

이 코드는 다음과 같은 과정을 거칩니다:

  1. PR 정보와 diff를 포함한 변수 준비
  2. Jinja2 템플릿 엔진 설정
  3. 시스템 및 사용자 프롬프트 렌더링
  4. 렌더링된 프롬프트로 AI 모델 호출
  5. AI 응답 반환

프롬프트 설계의 장점

PR-Agent의 프롬프트 설계는 몇 가지 주요 장점을 제공합니다:

1. 명확한 구조와 형식

Pydantic 모델 형식을 사용한 출력 구조 정의는 AI가 일관된 형식의 응답을 생성하도록 유도합니다. 이는 응답 파싱과 처리를 훨씬 쉽게 만듭니다.

2. 세부적인 지시사항

AI에게 무엇에 집중해야 하는지(새 코드), 무엇을 참고만 해야 하는지(기존 제목/설명), 어떻게 응답해야 하는지(YAML 형식) 등 세부적인 지시사항을 제공합니다.

3. 유연한 설정

템플릿 엔진을 활용한 조건부 콘텐츠는 다양한 설정 옵션에 따라 프롬프트를 동적으로 조정할 수 있게 합니다.

4. 대규모 PR 처리 능력

파일 전용/설명 전용 프롬프트 분리와 비동기 처리를 통해 대규모 PR도 효과적으로 분석할 수 있습니다.

AI 프롬프트 설계가 우리에게 주는 교훈

PR-Agent의 /describe 프롬프트 설계에서 배울 수 있는 몇 가지 중요한 교훈이 있습니다:

  1. 명확한 역할 정의: AI에게 구체적인 역할과 임무를 부여하세요.
  2. 구조화된 출력 형식: 원하는 출력 형식을 명확하게 정의하세요.
  3. 중요 정보 강조: AI가 어디에 집중해야 하는지 명확히 알려주세요.
  4. 템플릿 활용: 동적 프롬프트 생성으로 유연성을 높이세요.
  5. 대규모 작업 분할: 큰 작업은 작은 조각으로 나누어 처리하세요.

PR-Agent의 프롬프트 설계는 AI의 능력을 효과적으로 활용하여 유용하고 통찰력 있는 PR 설명을 생성하는 좋은 사례입니다. 이러한 설계 원칙은 다른 AI 애플리케이션에도 적용할 수 있으며, AI를 통해 더 가치 있는 결과물을 얻는 데 도움이 될 것입니다.

profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글