Merge pull request #1490 from hlohaus/neww

Improve doctypes in copilot
This commit is contained in:
H Lohaus 2024-01-21 16:59:52 +01:00 committed by GitHub
commit ca6da4c858
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 30 deletions

View File

@ -1,15 +1,17 @@
name: AI Code Reviewer name: AI Code Reviewer
on: on:
pull_request: workflow_run:
workflows: ["Unittest"]
types: types:
- opened - completed
- synchronize
jobs: jobs:
review: review:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: write-all permissions:
contents: read
pull-requests: write
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -25,5 +27,5 @@ jobs:
run: pip install PyGithub run: pip install PyGithub
- name: AI Code Review - name: AI Code Review
env: env:
GITHUB_TOKEN: ${{ secrets.COPILOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python -m etc.tool.copilot run: env

View File

@ -21,10 +21,13 @@ G4F_MODEL = os.getenv('G4F_MODEL') or g4f.models.gpt_4
def get_pr_details(github: Github) -> PullRequest: def get_pr_details(github: Github) -> PullRequest:
""" """
Rteurns the details of the pull request from GitHub. Retrieves the details of the pull request from GitHub.
Args:
github (Github): The Github object to interact with the GitHub API.
Returns: Returns:
PullRequest: A PullRequest instance. PullRequest: An object representing the pull request.
""" """
with open(os.getenv('GITHUB_EVENT_PATH', ''), 'r') as file: with open(os.getenv('GITHUB_EVENT_PATH', ''), 'r') as file:
data = json.load(file) data = json.load(file)
@ -36,19 +39,28 @@ def get_pr_details(github: Github) -> PullRequest:
def get_diff(diff_url: str) -> str: def get_diff(diff_url: str) -> str:
""" """
Fetches the diff of the pull request. Fetches the diff of the pull request from a given URL.
Args: Args:
pull (PullRequest): Pull request. diff_url (str): URL to the pull request diff.
Returns: Returns:
str or None: The diff of the pull request or None if not available. str: The diff of the pull request.
""" """
response = requests.get(diff_url) response = requests.get(diff_url)
response.raise_for_status() response.raise_for_status()
return response.text return response.text
def read_json(text: str) -> dict: def read_json(text: str) -> dict:
"""
Parses JSON code block from a string.
Args:
text (str): A string containing a JSON code block.
Returns:
dict: A dictionary parsed from the JSON code block.
"""
match = re.search(r"```(json|)\n(?P<code>[\S\s]+?)\n```", text) match = re.search(r"```(json|)\n(?P<code>[\S\s]+?)\n```", text)
if match: if match:
text = match.group("code") text = match.group("code")
@ -56,23 +68,33 @@ def read_json(text: str) -> dict:
return json.loads(text.strip()) return json.loads(text.strip())
except json.JSONDecodeError: except json.JSONDecodeError:
print("No valid json:", text) print("No valid json:", text)
return {} return {}
def read_text(text: str) -> dict: def read_text(text: str) -> str:
"""
Extracts text from a markdown code block.
Args:
text (str): A string containing a markdown code block.
Returns:
str: The extracted text.
"""
match = re.search(r"```(markdown|)\n(?P<text>[\S\s]+?)\n```", text) match = re.search(r"```(markdown|)\n(?P<text>[\S\s]+?)\n```", text)
if match: if match:
return match.group("text") return match.group("text")
return text return text
def get_ai_response(prompt, as_json: bool = True) -> Union[dict, str]: def get_ai_response(prompt: str, as_json: bool = True) -> Union[dict, str]:
""" """
Gets a response from g4f API based on the prompt. Gets a response from g4f API based on the prompt.
Args: Args:
prompt (str): The prompt to send to g4f. prompt (str): The prompt to send to g4f.
as_json (bool): Whether to parse the response as JSON.
Returns: Returns:
dict: The parsed response from g4f. Union[dict, str]: The parsed response from g4f, either as a dictionary or a string.
""" """
response = g4f.ChatCompletion.create( response = g4f.ChatCompletion.create(
G4F_MODEL, G4F_MODEL,
@ -80,20 +102,18 @@ def get_ai_response(prompt, as_json: bool = True) -> Union[dict, str]:
G4F_PROVIDER, G4F_PROVIDER,
ignore_stream_and_auth=True ignore_stream_and_auth=True
) )
if as_json: return read_json(response) if as_json else read_text(response)
return read_json(response)
return read_text(response)
def analyze_code(pull: PullRequest, diff: str)-> list: def analyze_code(pull: PullRequest, diff: str)-> list[dict]:
""" """
Analyzes the code changes in the pull request. Analyzes the code changes in the pull request.
Args: Args:
pull (PullRequest): The pull request object.
diff (str): The diff of the pull request. diff (str): The diff of the pull request.
pr_details (dict): Details of the pull request.
Returns: Returns:
list: List of comments generated by the analysis. list[dict]: A list of comments generated by the analysis.
""" """
comments = [] comments = []
changed_lines = [] changed_lines = []
@ -122,13 +142,14 @@ def analyze_code(pull: PullRequest, diff: str)-> list:
return comments return comments
def create_prompt(changed_lines: list, pull: PullRequest, file_path: str): def create_prompt(changed_lines: list[str], pull: PullRequest, file_path: str):
""" """
Creates a prompt for the g4f model. Creates a prompt for the g4f model.
Args: Args:
diff (str): The line of code to analyze. changed_lines (list[str]): The lines of code that have changed.
pr_details (dict): Details of the pull request. pull (PullRequest): The pull request object.
file_path (str): The path to the file being reviewed.
Returns: Returns:
str: The generated prompt. str: The generated prompt.
@ -159,16 +180,17 @@ Each line is prefixed by its number. Code to review:
def create_review_prompt(pull: PullRequest, diff: str): def create_review_prompt(pull: PullRequest, diff: str):
""" """
Creates a prompt to create a review. Creates a prompt to create a review comment.
Args: Args:
diff (str): The line of code to analyze. pull (PullRequest): The pull request object.
diff (str): The diff of the pull request.
Returns: Returns:
str: The generated prompt. str: The generated prompt for review.
""" """
return f"""Your task is to review a pull request. Instructions: return f"""Your task is to review a pull request. Instructions:
- Your name / you are copilot. - Write in name of you "g4f-copilot".
- Write the review in GitHub Markdown format. - Write the review in GitHub Markdown format.
- Thank the author for contributing to the project. - Thank the author for contributing to the project.
- Point out that you might leave a few comments on the files. - Point out that you might leave a few comments on the files.
@ -192,7 +214,7 @@ def main():
pull = get_pr_details(github) pull = get_pr_details(github)
diff = get_diff(pull.diff_url) diff = get_diff(pull.diff_url)
except Exception as e: except Exception as e:
print(f"Error get details: {e}") print(f"Error get details: {e.__class__.__name__}: {e}")
exit(1) exit(1)
try: try:
review = get_ai_response(create_review_prompt(pull, diff), False) review = get_ai_response(create_review_prompt(pull, diff), False)
@ -206,7 +228,10 @@ def main():
exit(1) exit(1)
print("Comments:", comments) print("Comments:", comments)
try: try:
pull.create_review(body=review, comments=comments) if not comments:
pull.create_review(body=review, comments=comments)
else:
pull.create_comment(body=review)
except Exception as e: except Exception as e:
print(f"Error posting review: {e}") print(f"Error posting review: {e}")
exit(1) exit(1)