從 get_prediction 我們可以查到他試著調用 system_prompt 跟 user_prompt 並喂給 ai_handler.chat_completion 進行AI 預測。
async def _get_prediction(self, model: str) -> str:
"""
Generate an AI prediction for the pull request review.
Args:
model: A string representing the AI model to be used for the prediction.
Returns:
A string representing the AI prediction for the pull request review.
"""
variables = copy.deepcopy(self.vars)
variables["diff"] = self.patches_diff # update diff
environment = Environment(undefined=StrictUndefined)
system_prompt = environment.from_string(get_settings().pr_review_prompt.system).render(variables)
user_prompt = environment.from_string(get_settings().pr_review_prompt.user).render(variables)
response, finish_reason = await self.ai_handler.chat_completion(
model=model,
temperature=get_settings().config.temperature,
system=system_prompt,
user=user_prompt
)
return response
而 system_prompt 跟 user_prompt 來自於 environment = Environment(undefined=StrictUndefined)。而 Environment 來自於外部的引入。這邊可以稍稍介紹 jinja2 Environment 的用途,他的設定 undefined=StrictUndefined 會在 Environment 是空值時拋出異常,而不是空值。所以這邊只是 environment 物件的引用。也算是多學會了對於環境的設定可以用 物件去包
from jinja2 import Environment, StrictUndefined
而實際 environment 的值來自於 get_settings(),可以得知get_setting 會從 starlette_context
的 context
獲取設定。如果沒取到,就使用global_settings
system_prompt = environment.from_string(get_settings().pr_review_prompt.system).render(variables)
user_prompt = environment.from_string(get_settings().pr_review_prompt.user).render(variables)
def get_settings():
"""
Retrieves the current settings.
This function attempts to fetch the settings from the starlette_context's context object. If it fails,
it defaults to the global settings defined outside of this function.
Returns:
Dynaconf: The current settings object, either from the context or the global default.
"""
try:
return context["settings"]
except Exception:
return global_settings
我們嘗試搜尋 pr_review_prompt 找到 pr-agent/pr_agent/settings/pr_reviewer_prompts.toml
的檔案,裡面是一連串使用 Jinja2 模板的語法(呼應到前面的 Jinja2 的 Environment
),
system="""You are PR-Reviewer, a language model designed to review a Git Pull Request (PR).
{%- if num_code_suggestions > 0 %}
Your task is to provide constructive and concise feedback for the PR, and also provide meaningful code suggestions.
{%- else %}
Your task is to provide constructive and concise feedback for the PR.
{%- endif %}
The review should focus on new code added in the PR diff (lines starting with '+')
render 的 variables 則代表 title
、branch
、description
、diff
在 pr_review_prompt.system 的部分,他先定義了 AI 的角色:專門用於 Git Pull Request 審查的模型
You are PR-Reviewer, a language model designed to review a Git Pull Request (PR).
並對此角色進行任務定義,這邊會根據 num_code_suggestions 進行調整,有只給 feedback or feedback + code suggestions
{%- if num_code_suggestions > 0 %}
Your task is to provide constructive and concise feedback for the PR, and also provide meaningful code suggestions.
{%- else %}
Your task is to provide constructive and concise feedback for the PR.
{%- endif %}
想辦法讓 AI 更清楚地理解這份檔案
The format we will use to present the PR code diff:
======
## file: 'src/file1.py'
@@ ... @@ def func1():
__new hunk__
12 code line1 that remained unchanged in the PR
13 +new hunk code line2 added in the PR
14 code line3 that remained unchanged in the PR
__old hunk__
code line1 that remained unchanged in the PR
-old hunk code line2 that was removed in the PR
code line3 that remained unchanged in the PR
@@ ... @@ def func2():
__new hunk__
...
__old hunk__
...
## file: 'src/file2.py'
...
======
- In this format, we separated each hunk of diff code to '__new hunk__' and '__old hunk__' sections. The '__new hunk__' section contains the new code of the chunk, and the '__old hunk__' section contains the old code, that was removed.
- We also added line numbers for the '__new hunk__' sections, to help you refer to the code lines in your suggestions. These line numbers are not part of the actual code, and are only used for reference.
- Code lines are prefixed with symbols ('+', '-', ' '). The '+' symbol indicates new code added in the PR, the '-' symbol indicates code removed in the PR, and the ' ' symbol indicates unchanged code. \
The review should focus on new code added in the PR diff (lines starting with '+')
- When quoting variables or names from the code, use backticks (`) instead of single quote (').
提醒聚焦在有變更的地方
The review should focus on new code added in the PR diff (lines starting with '+')
用戶如果有想自己新增的提示,也可以補充在這
{%- if extra_instructions %}
Extra instructions from the user:
======
{{ extra_instructions }}
======
{% endif %}
研究到這邊,算是比較理解,啊,原來人家是這樣玩 AI 並把它做成工具。也比較清楚之後自己想玩的地方,之後繼續花時間拆解其他有趣部分