Merge branch 'main' into mrT23-patch-1

This commit is contained in:
Tal
2024-01-24 09:58:23 -08:00
committed by GitHub
7 changed files with 144 additions and 34 deletions

View File

@ -32,11 +32,9 @@ Making pull requests less painful with an AI agent
- [Why use PR-Agent?](#why-use-pr-agent) - [Why use PR-Agent?](#why-use-pr-agent)
## News and Updates ## News and Updates
### Jan 18, 2024 ### Jan 21, 2024
We are very happy to share our new paper: - 💎 Custom suggestions - A new tool, `/custom_suggestions`, was added to PR-Agent Pro. The tool will propose only suggestions that follow specific guidelines defined by the user.
**"Code Generation with AlphaCodium: From Prompt Engineering to Flow Engineering".** See [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/CUSTOM_SUGGESTIONS.md) for more details.
Go checkout our official implementation [here](https://github.com/Codium-ai/AlphaCodium)
### Jan 17, 2024 ### Jan 17, 2024
- 💎 Inline file summary - The `describe` tool has a new option `--pr_description.inline_file_summary`, which allows to add a summary of each file changes to the Diffview page. See [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-) - 💎 Inline file summary - The `describe` tool has a new option `--pr_description.inline_file_summary`, which allows to add a summary of each file changes to the Diffview page. See [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-)
@ -75,6 +73,8 @@ CodiumAI PR-Agent is an open-source tool to help efficiently review and handle p
**Generate Custom Labels 💎 ([`/generate_labels`](./docs/GENERATE_CUSTOM_LABELS.md))**: Automatically suggests custom labels based on the PR code changes. **Generate Custom Labels 💎 ([`/generate_labels`](./docs/GENERATE_CUSTOM_LABELS.md))**: Automatically suggests custom labels based on the PR code changes.
\ \
**Analyze 💎 ([`/analyze`](./docs/Analyze.md))**: Automatically analyzes the PR, and presents changes walkthrough for each component. **Analyze 💎 ([`/analyze`](./docs/Analyze.md))**: Automatically analyzes the PR, and presents changes walkthrough for each component.
\
**Custom Suggestions 💎 ([`/custom_suggestions`](./docs/CUSTOM_SUGGESTIONS.md))**: Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user.
See the [Installation Guide](./INSTALL.md) for instructions on installing and running the tool on different git platforms. See the [Installation Guide](./INSTALL.md) for instructions on installing and running the tool on different git platforms.
@ -89,7 +89,7 @@ See the [Tools Guide](./docs/TOOLS_GUIDE.md) for a detailed description of the d
<h4><a href="https://github.com/Codium-ai/pr-agent/pull/530">/describe</a></h4> <h4><a href="https://github.com/Codium-ai/pr-agent/pull/530">/describe</a></h4>
<div align="center"> <div align="center">
<p float="center"> <p float="center">
<img src="https://www.codium.ai/images/pr_agent/describe_short_main.png" width="800"> <img src="https://www.codium.ai/images/pr_agent/describe_new_short_main.png" width="800">
</p> </p>
</div> </div>
<hr> <hr>
@ -164,6 +164,7 @@ See the [Tools Guide](./docs/TOOLS_GUIDE.md) for a detailed description of the d
| | ⮑ [Inline file summary](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-) 💎 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | ⮑ [Inline file summary](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-) 💎 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Improve | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | Improve | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | ⮑ Extended | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | ⮑ Extended | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | [Custom Suggestions](https://github.com/Codium-ai/pr-agent/blob/main/docs/CUSTOM_SUGGESTIONS.md) 💎 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Reflect and Review | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | Reflect and Review | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Update CHANGELOG.md | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | Update CHANGELOG.md | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Find Similar Issue | :white_check_mark: | | | | | Find Similar Issue | :white_check_mark: | | |

View File

@ -0,0 +1,65 @@
# Custom Suggestions Tool 💎
## Table of Contents
- [Overview](#overview)
- [Example usage](#example-usage)
- [Configuration options](#configuration-options)
## Overview
The `custom_suggestions` tool scans the PR code changes, and automatically generates custom suggestions for improving the PR code.
It shares similarities with the `improve` tool, but with one main difference: the `custom_suggestions` tool will only propose suggestions that follow specific guidelines defined by the prompt in: `pr_custom_suggestions.prompt` configuration.
The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on a PR.
When commenting, use the following template:
```
/custom_suggestions --pr_custom_suggestions.prompt="The suggestions should focus only on the following:\n-...\n-...\n-..."
```
With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template:
```
[pr_custom_suggestions]
prompt="""\
The suggestions should focus only on the following:
-...
-...
-...
"""
```
Using a configuration file is recommended, since it allows to use multi-line instructions.
Don't forget - with this tool, you are the prompter. Be specific, clear, and concise in the instructions. Specify relevant aspects that you want the model to focus on. \
You might benefit from several trial-and-error iterations, until you get the correct prompt for your use case.
## Example usage
Here is an example of a possible prompt:
```
[pr_custom_suggestions]
prompt="""\
The suggestions should focus only on the following:
- look for edge cases when implementing a new function
- make sure every variable has a meaningful name
- make sure the code is efficient
"""
```
The instructions above are just an example. We want to emphasize that the prompt should be specific and clear, and be tailored to the needs of your project.
Results obtained with the prompt above:
___
<kbd><img src=https://codium.ai/images/pr_agent/custom_suggestions_prompt.png width="512"></kbd>
___
<kbd><img src=https://codium.ai/images/pr_agent/custom_suggestions_result.png width="768"></kbd>
___
## Configuration options
`prompt`: the prompt for the tool. It should be a multi-line string.
`num_code_suggestions`: number of code suggestions provided by the 'custom_suggestions' tool. Default is 4.
`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true.

View File

@ -20,7 +20,7 @@ For example:
___ ___
<kbd><img src=https://codium.ai/images/pr_agent/describe_comment.png width="768"></kbd> <kbd><img src=https://codium.ai/images/pr_agent/describe_comment.png width="768"></kbd>
___ ___
<kbd><img src=https://codium.ai/images/pr_agent/describe.png width="768"></kbd> <kbd><img src=https://codium.ai/images/pr_agent/describe_new.png width="768"></kbd>
___ ___
### Configuration options ### Configuration options
@ -50,12 +50,15 @@ To edit [configurations](./../pr_agent/settings/configuration.toml#L46) related
- `collapsible_file_list`: if set to true, the file list in the "Changes walkthrough" section will be collapsible. If set to "adaptive", the file list will be collapsible only if there are more than 8 files. Default is "adaptive". - `collapsible_file_list`: if set to true, the file list in the "Changes walkthrough" section will be collapsible. If set to "adaptive", the file list will be collapsible only if there are more than 8 files. Default is "adaptive".
### Inline file summary 💎 ### Inline file summary 💎
To enable inline file summary, set `pr_description.inline_file_summary=true` in the configuration file. > This feature is available only in PR-Agent Pro
When the feature is enabled, PR-Agent Pro will add a collapsable summary of each file change in the "Files changed" tab.
This will enable you to quickly understand the changes in each file, while reviewing the code changes (diff view). This will enable you to quickly understand the changes in each file, while reviewing the code changes (diff view).
To enable inline file summary, set `pr_description.inline_file_summary` in the configuration file, possible values are:
- `'table'`: File changes walkthrough table will be displayed on the top of the "Files changed" tab, in addition to the "Conversation" tab.
<kbd><img src=https://codium.ai/images/pr_agent/diffview-table.png width="1024"></kbd>
- `true`: A collapsable file comment with changes title and a changes summary for each file in the PR.
<kbd><img src=https://codium.ai/images/pr_agent/diffview_changes.png width="1024"></kbd> <kbd><img src=https://codium.ai/images/pr_agent/diffview_changes.png width="1024"></kbd>
- `false` (`default`): File changes walkthrough will be added only to the "Conversation" tab.
*Note that this feature is currently available only for GitHub. *Note that this feature is currently available only for GitHub.

View File

@ -175,6 +175,17 @@ Make sure to provide proper title, and a detailed and well-phrased description f
""" """
output += "\n\n</details></td></tr>\n\n" output += "\n\n</details></td></tr>\n\n"
# Inline File Walkthrough
output += "<tr><td><details> <summary><strong> Inline File Walkthrough 💎</strong></summary><hr>\n\n"
output += """\
For enhanced user experience, the `describe` tool can add file summaries directly to the "Files changed" tab in the PR page.
This will enable you to quickly understand the changes in each file, while reviewing the code changes (diffs).
To enable inline file summary, set `pr_description.inline_file_summary` in the configuration file, possible values are:
- `'table'`: File changes walkthrough table will be displayed on the top of the "Files changed" tab, in addition to the "Conversation" tab.
- `true`: A collapsable file comment with changes title and a changes summary for each file in the PR.
- `false` (default): File changes walkthrough will be added only to the "Conversation" tab.
"""
# extra instructions # extra instructions
output += "<tr><td><details> <summary><strong> Utilizing extra instructions</strong></summary><hr>\n\n" output += "<tr><td><details> <summary><strong> Utilizing extra instructions</strong></summary><hr>\n\n"
output += '''\ output += '''\

View File

@ -56,7 +56,7 @@ enable_help_text=true
## changes walkthrough section ## changes walkthrough section
enable_semantic_files_types=true enable_semantic_files_types=true
collapsible_file_list='adaptive' # true, false, 'adaptive' collapsible_file_list='adaptive' # true, false, 'adaptive'
inline_file_summary=true # Pro feature inline_file_summary=false # false, true, 'table'
# markers # markers
use_description_markers=false use_description_markers=false
include_generated_by_header=true include_generated_by_header=true

View File

@ -39,7 +39,8 @@ class PRType(str, Enum):
Class FileDescription(BaseModel): Class FileDescription(BaseModel):
filename: str = Field(description="the relevant file full path") filename: str = Field(description="the relevant file full path")
changes_summary: str = Field(description="minimal and concise summary of the changes in the relevant file") changes_summary: str = Field(description="concise summary of the changes in the relevant file, in bullet points (1-4 bullet points).")
changes_title: str = Field(description="an informative title for the changes in the files, describing its main theme (5-10 words).")
label: str = Field(description="a single semantic label that represents a type of code changes that occurred in the File. Possible values (partial list): 'bug fix', 'tests', 'enhancement', 'documentation', 'error handling', 'configuration changes', 'dependencies', 'formatting', 'miscellaneous', ...") label: str = Field(description="a single semantic label that represents a type of code changes that occurred in the File. Possible values (partial list): 'bug fix', 'tests', 'enhancement', 'documentation', 'error handling', 'configuration changes', 'dependencies', 'formatting', 'miscellaneous', ...")
{%- endif %} {%- endif %}
@ -68,6 +69,8 @@ pr_files:
... ...
changes_summary: | changes_summary: |
... ...
changes_title: |
...
label: | label: |
... ...
... ...

View File

@ -333,10 +333,11 @@ class PRDescription:
try: try:
filename = file['filename'].replace("'", "`").replace('"', '`') filename = file['filename'].replace("'", "`").replace('"', '`')
changes_summary = file['changes_summary'] changes_summary = file['changes_summary']
changes_title = file['changes_title'].strip()
label = file.get('label') label = file.get('label')
if label not in self.file_label_dict: if label not in self.file_label_dict:
self.file_label_dict[label] = [] self.file_label_dict[label] = []
self.file_label_dict[label].append((filename, changes_summary)) self.file_label_dict[label].append((filename, changes_title, changes_summary))
except Exception as e: except Exception as e:
get_logger().error(f"Error preparing file label dict {self.pr_id}: {e}") get_logger().error(f"Error preparing file label dict {self.pr_id}: {e}")
pass pass
@ -357,9 +358,9 @@ class PRDescription:
try: try:
pr_body += "<table>" pr_body += "<table>"
header = f"Relevant files" header = f"Relevant files"
delta = 65 delta = 77
header += "&nbsp; " * delta # header += "&nbsp; " * delta
pr_body += f"""<thead><tr><th></th><th>{header}</th></tr></thead>""" pr_body += f"""<thead><tr><th></th><th align="left">{header}</th></tr></thead>"""
pr_body += """<tbody>""" pr_body += """<tbody>"""
for semantic_label in value.keys(): for semantic_label in value.keys():
s_label = semantic_label.strip("'").strip('"') s_label = semantic_label.strip("'").strip('"')
@ -370,19 +371,24 @@ class PRDescription:
pr_body += f"""<td><details><summary>{len(list_tuples)} files</summary><table>""" pr_body += f"""<td><details><summary>{len(list_tuples)} files</summary><table>"""
else: else:
pr_body += f"""<td><table>""" pr_body += f"""<td><table>"""
for filename, file_change_description in list_tuples: for filename, file_changes_title, file_change_description in list_tuples:
filename = filename.replace("'", "`") filename = filename.replace("'", "`")
filename_publish = filename.split("/")[-1] filename_publish = filename.split("/")[-1]
filename_publish = f"{filename_publish}" file_changes_title_br = insert_br_after_x_chars(file_changes_title, x=(delta - 5),
if len(filename_publish) < (delta - 5): new_line_char="\n\n")
filename_publish += "&nbsp; " * ((delta - 5) - len(filename_publish)) file_changes_title_extended = file_changes_title_br.strip() + "</code>"
if len(file_changes_title_extended) < (delta - 5):
file_changes_title_extended += "&nbsp; " * ((delta - 5) - len(file_changes_title_extended))
filename_publish = f"<strong>{filename_publish}</strong><dd><code>{file_changes_title_extended}</dd>"
diff_plus_minus = "" diff_plus_minus = ""
delta_nbsp = ""
diff_files = self.git_provider.diff_files diff_files = self.git_provider.diff_files
for f in diff_files: for f in diff_files:
if f.filename.lower() == filename.lower(): if f.filename.lower() == filename.lower():
num_plus_lines = f.num_plus_lines num_plus_lines = f.num_plus_lines
num_minus_lines = f.num_minus_lines num_minus_lines = f.num_minus_lines
diff_plus_minus += f"+{num_plus_lines}/-{num_minus_lines}" diff_plus_minus += f"+{num_plus_lines}/-{num_minus_lines}"
delta_nbsp = "&nbsp; " * max(0, (8 - len(diff_plus_minus)))
break break
# try to add line numbers link to code suggestions # try to add line numbers link to code suggestions
@ -391,21 +397,19 @@ class PRDescription:
filename = filename.strip() filename = filename.strip()
link = self.git_provider.get_line_link(filename, relevant_line_start=-1) link = self.git_provider.get_line_link(filename, relevant_line_start=-1)
file_change_description = insert_br_after_x_chars(file_change_description, x=(delta - 5)) file_change_description_br = insert_br_after_x_chars(file_change_description, x=(delta - 5))
pr_body += f""" pr_body += f"""
<tr> <tr>
<td> <td>
<details> <details>
<summary><strong>{filename_publish}</strong></summary> <summary>{filename_publish}</summary>
<ul> <hr>
{filename}<br><br>
**{file_change_description}** {filename}
</ul> {file_change_description_br}
</details> </details>
</td> </td>
<td><a href="{link}"> {diff_plus_minus}</a></td> <td><a href="{link}">{diff_plus_minus}</a>{delta_nbsp}</td>
</tr> </tr>
""" """
if use_collapsible_file_list: if use_collapsible_file_list:
@ -419,25 +423,48 @@ class PRDescription:
pass pass
return pr_body return pr_body
def insert_br_after_x_chars(text, x=70): def insert_br_after_x_chars(text, x=70, new_line_char="<br> "):
""" """
Insert <br> into a string after a word that increases its length above x characters. Insert <br> into a string after a word that increases its length above x characters.
""" """
if len(text) < x: if len(text) < x:
return text return text
words = text.split(' ') lines = text.splitlines()
words = []
for i,line in enumerate(lines):
words += line.split(' ')
if i<len(lines)-1:
words[-1] += "\n"
# words = text.split(' ')
new_text = "" new_text = ""
current_length = 0 current_length = 0
is_inside_code = False
for word in words: for word in words:
# Check if adding this word exceeds x characters # Check if adding this word exceeds x characters
if current_length + len(word) > x: if current_length + len(word) > x:
new_text += "<br>" # Insert line break if not is_inside_code:
new_text += f"{new_line_char} " # Insert line break
current_length = 0 # Reset counter current_length = 0 # Reset counter
else:
new_text += f"`{new_line_char} `"
# check if inside <code> tag
if word.startswith("`") and not is_inside_code and not word.endswith("`"):
is_inside_code = True
if word.endswith("`"):
is_inside_code = False
# Add the word to the new text # Add the word to the new text
if word.endswith("\n"):
new_text += word
else:
new_text += word + " " new_text += word + " "
current_length += len(word) + 1 # Add 1 for the space current_length += len(word) + 1 # Add 1 for the space
if word.endswith("\n"):
current_length = 0
return new_text.strip() # Remove trailing space return new_text.strip() # Remove trailing space