Created
March 19, 2024 11:26
-
-
Save alexcpn/3db8b4999ec96b6f0a5fb1cc3a16fa73 to your computer and use it in GitHub Desktop.
Autogen based CodeReview with two bots a GPT3 (devloper) and GPT4 (Tech lead) and also using classic linter tools
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Run Server like | |
python3 -m llama_cpp.server --model /home/alex/coding/Mistral-7B-Instruct-v0.2-GGUF/mistral-7b-instruct-v0.2.Q4_K_M.gguf --host localhost --port 8080 | |
""" | |
# Autogen code adapated from https://microsoft.github.io/autogen/docs/Examples/#multi-agent-collaboration-3-agents | |
import autogen | |
import pylint.lint | |
from pylint.reporters.text import TextReporter | |
from io import StringIO | |
import os | |
#------------------------------------------------------------------------Configurations------------------------------------- | |
config_list_low = [ | |
{ | |
"model":"mistral-instruct-v0.2", | |
"base_url": "http://localhost:8080/v1", | |
"api_key":"NULL" | |
} | |
,{ | |
"model": "gpt-3.5-turbo-1106", # model name | |
"api_key": "your key" # api key | |
} | |
] | |
high_config = { | |
"cache_seed": 442, | |
"temperature": 0, | |
"config_list": [ | |
{ | |
"model": "gpt-4-0613", # model name | |
"api_key": "your key # api key | |
} | |
], | |
} | |
#----------------------------------------Agents and Agent Proxies ------------------------------------------------------------------------------------ | |
developer_agent = autogen.AssistantAgent( | |
name="developer_agent", | |
system_message="""You are a helpful code reivew assistant.\ | |
Use code_linter first to get the pylint errors to help in review. | |
Use ask_expert function with your review comments for a more thorough review.Reply TERMINATE when the task is done.""", | |
llm_config={ | |
"timeout": 600, | |
"cache_seed": 42, | |
"config_list": config_list_low, | |
"temperature": 0, | |
"functions": [ | |
{ | |
"name": "ask_expert", | |
"description": "An Expert Code Review agent", | |
"parameters": { | |
"type": "object", | |
"properties": { | |
"message": { | |
"type": "string", | |
"description": "your review comments", | |
}, | |
"code_snippet": { | |
"type": "string", | |
"description": "original code snippet", | |
}, | |
}, | |
"required": ["code_snippet","message"], | |
}, | |
}, | |
{ | |
"name": "code_linter", | |
"description": "Use Pylint as a tool for intial review", | |
"parameters": { | |
"type": "object", | |
"properties": { | |
"code_snippet": { | |
"type": "string", | |
"description": "The code snippet to review", | |
}, | |
}, | |
"required": ["code_snippet"], | |
}, | |
} | |
], | |
}, | |
) | |
#----------------------------------------Functions ------------------------------------------------------------------------------------ | |
def lint_code_snippet(code_snippet): | |
"""Lints a code snippet using pylint.""" | |
temp_file_path = 'temp.py' | |
# Create a temporary file to write the code snippet to, as PyLinter requires file paths | |
with open(temp_file_path, 'w') as temp_file: | |
temp_file.write(code_snippet) | |
# Setup the in-memory output stream for pylint reports | |
output = StringIO() | |
# Initialize the linter | |
linter = pylint.lint.PyLinter(reporter=TextReporter(output=output)) | |
linter.load_default_plugins() # Load the default pylint plugins | |
linter.check([temp_file_path]) | |
os.remove(temp_file_path) | |
# Return the captured output | |
return output.getvalue() | |
def ask_expert(code_snippet,message): | |
print(f"In ask_expert code_snippet={code_snippet} message={message}") | |
expert_agent = autogen.AssistantAgent( | |
name="expert_agent", | |
system_message="""you are a helpful assistant highly skilled in evaluating given code by providing a score from 1 (bad) - 10 (good) | |
while providing clear rationale. | |
Specifically, you can carefully evaluate the code across the following dimensions | |
- bugs (bugs): are there bugs, logic errors, syntax error or typos? | |
- performance (optimization): is the code effecient? can you suggest tips for better performance ? | |
- security (compliance): Are good security practices followed. Give score as NA if this is not applicable | |
- readability/maintainability:: How readable and maintainable is the code | |
YOU MUST PROVIDE A SCORE for each of the above dimensions froma score from 1 (bad) - 10 (good) | |
{bugs: 0, performance: 0, security: 0, readability/maintainability: 0} | |
Finally, based on the critique above, suggest a concrete list of actions that the coder should take to improve the code. | |
""", | |
llm_config=high_config | |
) | |
expert = autogen.UserProxyAgent( | |
name="expert", | |
human_input_mode="NEVER", | |
max_consecutive_auto_reply=2, | |
code_execution_config= False, # disable code executiong | |
) | |
expert.initiate_chat(expert_agent,message=f"For the followin code \n '{code_snippet}' \n these are the initial code review comments " + | |
f"along with pylint findings \n '{message}'") | |
#expert.stop_reply_at_receive(expert_agent) | |
# final message sent from the expert | |
expert.send(f"Summarise and show code snippets for the comments if possible", expert_agent) | |
# return the last message the expert received | |
return expert.last_message()["content"] | |
developer = autogen.UserProxyAgent( | |
name="developer", | |
human_input_mode="NEVER", | |
max_consecutive_auto_reply=2, | |
code_execution_config={ | |
"work_dir": "developer", | |
"use_docker": False, | |
}, | |
function_map={"code_linter": lint_code_snippet,"ask_expert": ask_expert} | |
) | |
#----------------------------------------------------------------------------------------------------------------------------- | |
if __name__ == "__main__": | |
print ("Autogen Bots for Code Review") | |
code_snippet=""" | |
for message in messages: | |
email_data = dict() | |
msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute() | |
headers = msg['payload']['headers'] | |
date = next(header['value'] for header in headers if header['name'] == 'Date') | |
print(f"Date: {date}") | |
email_data["date"]= date | |
""" | |
# the assistant receives a message with code review parts | |
developer.initiate_chat( | |
developer_agent, | |
message=code_snippet, | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tranformer_learn$ /usr/bin/python3 /ssd/tranformer_learn/autogen_test.py | |
/usr/lib/python3/dist-packages/pkg_resources/__init__.py:116: PkgResourcesDeprecationWarning: 2.22.1ubuntu1 is an invalid version and will not be supported in a future release | |
warnings.warn( | |
/usr/lib/python3/dist-packages/pkg_resources/__init__.py:116: PkgResourcesDeprecationWarning: 0.1.43ubuntu1 is an invalid version and will not be supported in a future release | |
warnings.warn( | |
Autogen Bots for Code Review | |
developer (to developer_agent): | |
for message in messages: | |
email_data = dict() | |
msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute() | |
headers = msg['payload']['headers'] | |
date = next(header['value'] for header in headers if header['name'] == 'Date') | |
print(f"Date: {date}") | |
email_data["date"]= date | |
-------------------------------------------------------------------------------- | |
developer_agent (to developer): | |
***** Suggested function Call: code_linter ***** | |
Arguments: | |
{"code_snippet":"for message in messages:\n email_data = dict()\n msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute()\n\n headers = msg['payload']['headers']\n date = next(header['value'] for header in headers if header['name'] == 'Date')\n print(f\"Date: {date}\")\n email_data[\"date\"]= date"} | |
************************************************ | |
-------------------------------------------------------------------------------- | |
>>>>>>>> EXECUTING FUNCTION code_linter... | |
developer (to developer_agent): | |
***** Response from calling function "code_linter" ***** | |
************* Module temp | |
temp.py:8:0: C0304: Final newline missing (missing-final-newline) | |
temp.py:1:0: C0114: Missing module docstring (missing-module-docstring) | |
temp.py:1:15: E0602: Undefined variable 'messages' (undefined-variable) | |
temp.py:2:17: R1735: Consider using '{}' instead of a call to 'dict'. (use-dict-literal) | |
temp.py:3:10: E0602: Undefined variable 'service' (undefined-variable) | |
******************************************************** | |
-------------------------------------------------------------------------------- | |
developer_agent (to developer): | |
***** Suggested function Call: ask_expert ***** | |
Arguments: | |
{"message":"The code is missing a final newline and a module docstring. It also has undefined variables 'messages' and 'service'. Consider using '{}' instead of a call to 'dict'.","code_snippet":"for message in messages:\n email_data = dict()\n msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute()\n\n headers = msg['payload']['headers']\n date = next(header['value'] for header in headers if header['name'] == 'Date')\n print(f\"Date: {date}\")\n email_data[\"date\"]= date"} | |
*********************************************** | |
-------------------------------------------------------------------------------- | |
>>>>>>>> EXECUTING FUNCTION ask_expert... | |
In ask_expert code_snippet=for message in messages: | |
email_data = dict() | |
msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute() | |
headers = msg['payload']['headers'] | |
date = next(header['value'] for header in headers if header['name'] == 'Date') | |
print(f"Date: {date}") | |
email_data["date"]= date message=The code is missing a final newline and a module docstring. It also has undefined variables 'messages' and 'service'. Consider using '{}' instead of a call to 'dict'. | |
expert (to expert_agent): | |
For the followin code | |
'for message in messages: | |
email_data = dict() | |
msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute() | |
headers = msg['payload']['headers'] | |
date = next(header['value'] for header in headers if header['name'] == 'Date') | |
print(f"Date: {date}") | |
email_data["date"]= date' | |
these are the initial code review comments along with pylint findings | |
'The code is missing a final newline and a module docstring. It also has undefined variables 'messages' and 'service'. Consider using '{}' instead of a call to 'dict'.' | |
-------------------------------------------------------------------------------- | |
expert_agent (to expert): | |
Based on the provided code and the initial review comments, here is the evaluation: | |
- Bugs: 4/10 | |
The code has undefined variables 'messages' and 'service'. These variables need to be defined or passed as arguments to the function. Also, the code is missing a final newline which is a common practice in Python to indicate the end of a file. | |
- Performance: 6/10 | |
The code seems to be fetching each message one by one in a loop. If the 'messages' list is large, this could lead to performance issues. It would be more efficient to fetch all messages at once if the API allows it. | |
- Security: NA | |
The code does not involve any explicit security measures like encryption, user authentication, etc. Therefore, it's not applicable to rate the security aspect. | |
- Readability/Maintainability: 5/10 | |
The code is relatively simple and easy to understand. However, it lacks comments and docstrings which are important for readability and maintainability. Also, using 'dict()' to create a dictionary is less readable than using '{}'. | |
To improve the code, the coder should: | |
1. Define or pass 'messages' and 'service' as arguments to the function. | |
2. Add a final newline at the end of the file. | |
3. Replace 'dict()' with '{}' to create a dictionary. | |
4. Add comments and docstrings to explain what the code does. | |
5. Consider fetching all messages at once for better performance if the API allows it. | |
-------------------------------------------------------------------------------- | |
expert (to expert_agent): | |
-------------------------------------------------------------------------------- | |
expert_agent (to expert): | |
I'm sorry, but it seems like you didn't provide any code or question for me to evaluate. Could you please provide more details or ask a specific question? | |
-------------------------------------------------------------------------------- | |
expert (to expert_agent): | |
-------------------------------------------------------------------------------- | |
expert_agent (to expert): | |
I'm sorry, but it seems like you didn't provide any code or question for me to evaluate. Could you please provide more details or ask a specific question? | |
-------------------------------------------------------------------------------- | |
expert (to expert_agent): | |
Summarise and show code snippets for the comments if possible | |
-------------------------------------------------------------------------------- | |
expert_agent (to expert): | |
Sure, here's a summary of the comments with code snippets: | |
1. Define or pass 'messages' and 'service' as arguments to the function. | |
The variables 'messages' and 'service' are not defined in the code. They should be defined or passed as arguments to the function. Here's how you can pass them as arguments: | |
```python | |
def process_messages(service, messages): | |
for message in messages: | |
# rest of the code | |
``` | |
2. Add a final newline at the end of the file. | |
A final newline is a common practice in Python to indicate the end of a file. Simply press 'Enter' at the end of your last line of code. | |
3. Replace 'dict()' with '{}' to create a dictionary. | |
Using '{}' to create a dictionary is more readable and pythonic than using 'dict()'. Here's how you can do it: | |
```python | |
email_data = {} | |
``` | |
4. Add comments and docstrings to explain what the code does. | |
Comments and docstrings are important for readability and maintainability. Here's how you can add them: | |
```python | |
def process_messages(service, messages): | |
""" | |
This function processes messages and prints their dates. | |
""" | |
# Loop through each message | |
for message in messages: | |
# rest of the code | |
``` | |
5. Consider fetching all messages at once for better performance if the API allows it. | |
If the 'messages' list is large, fetching each message one by one could lead to performance issues. If the API allows it, consider fetching all messages at once. This would require changes in the API call and is not shown in the code snippet. | |
-------------------------------------------------------------------------------- | |
expert (to expert_agent): | |
-------------------------------------------------------------------------------- | |
expert_agent (to expert): | |
Sure, here's a summary of the comments with code snippets: | |
1. Define or pass 'messages' and 'service' as arguments to the function. | |
The variables 'messages' and 'service' are not defined in the code. They should be defined or passed as arguments to the function. Here's how you can pass them as arguments: | |
```python | |
def process_messages(service, messages): | |
for message in messages: | |
# rest of the code | |
``` | |
2. Add a final newline at the end of the file. | |
A final newline is a common practice in Python to indicate the end of a file. Simply press 'Enter' at the end of your last line of code. | |
3. Replace 'dict()' with '{}' to create a dictionary. | |
Using '{}' to create a dictionary is more readable and pythonic than using 'dict()'. Here's how you can do it: | |
```python | |
email_data = {} | |
``` | |
4. Add comments and docstrings to explain what the code does. | |
Comments and docstrings are important for readability and maintainability. Here's how you can add them: | |
```python | |
def process_messages(service, messages): | |
""" | |
This function processes messages and prints their dates. | |
""" | |
# Loop through each message | |
for message in messages: | |
# rest of the code | |
``` | |
5. Consider fetching all messages at once for better performance if the API allows it. | |
If the 'messages' list is large, fetching each message one by one could lead to performance issues. If the API allows it, consider fetching all messages at once. This would require changes in the API call and is not shown in the code snippet. | |
-------------------------------------------------------------------------------- | |
expert (to expert_agent): | |
-------------------------------------------------------------------------------- | |
expert_agent (to expert): | |
Sure, here's a summary of the comments with code snippets: | |
1. Define or pass 'messages' and 'service' as arguments to the function. | |
The variables 'messages' and 'service' are not defined in the code. They should be defined or passed as arguments to the function. Here's how you can pass them as arguments: | |
```python | |
def process_messages(service, messages): | |
for message in messages: | |
# rest of the code | |
``` | |
2. Add a final newline at the end of the file. | |
A final newline is a common practice in Python to indicate the end of a file. Simply press 'Enter' at the end of your last line of code. | |
3. Replace 'dict()' with '{}' to create a dictionary. | |
Using '{}' to create a dictionary is more readable and pythonic than using 'dict()'. Here's how you can do it: | |
```python | |
email_data = {} | |
``` | |
4. Add comments and docstrings to explain what the code does. | |
Comments and docstrings are important for readability and maintainability. Here's how you can add them: | |
```python | |
def process_messages(service, messages): | |
""" | |
This function processes messages and prints their dates. | |
""" | |
# Loop through each message | |
for message in messages: | |
# rest of the code | |
``` | |
5. Consider fetching all messages at once for better performance if the API allows it. | |
If the 'messages' list is large, fetching each message one by one could lead to performance issues. If the API allows it, consider fetching all messages at once. This would require changes in the API call and is not shown in the code snippet. | |
-------------------------------------------------------------------------------- | |
developer (to developer_agent): | |
***** Response from calling function "ask_expert" ***** | |
Sure, here's a summary of the comments with code snippets: | |
1. Define or pass 'messages' and 'service' as arguments to the function. | |
The variables 'messages' and 'service' are not defined in the code. They should be defined or passed as arguments to the function. Here's how you can pass them as arguments: | |
```python | |
def process_messages(service, messages): | |
for message in messages: | |
# rest of the code | |
``` | |
2. Add a final newline at the end of the file. | |
A final newline is a common practice in Python to indicate the end of a file. Simply press 'Enter' at the end of your last line of code. | |
3. Replace 'dict()' with '{}' to create a dictionary. | |
Using '{}' to create a dictionary is more readable and pythonic than using 'dict()'. Here's how you can do it: | |
```python | |
email_data = {} | |
``` | |
4. Add comments and docstrings to explain what the code does. | |
Comments and docstrings are important for readability and maintainability. Here's how you can add them: | |
```python | |
def process_messages(service, messages): | |
""" | |
This function processes messages and prints their dates. | |
""" | |
# Loop through each message | |
for message in messages: | |
# rest of the code | |
``` | |
5. Consider fetching all messages at once for better performance if the API allows it. | |
If the 'messages' list is large, fetching each message one by one could lead to performance issues. If the API allows it, consider fetching all messages at once. This would require changes in the API call and is not shown in the code snippet. | |
******************************************************* | |
-------------------------------------------------------------------------------- | |
developer_agent (to developer): | |
I have provided a summary of the comments along with code snippets. Please review and make the necessary changes. If you need further assistance, feel free to ask! | |
-------------------------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment