Skip to content

Instantly share code, notes, and snippets.

@alexcpn
Created March 19, 2024 11:26
Show Gist options
  • Save alexcpn/3db8b4999ec96b6f0a5fb1cc3a16fa73 to your computer and use it in GitHub Desktop.
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
"""
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,
)
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