mirror of
https://github.com/Aider-AI/aider.git
synced 2025-06-02 02:34:59 +00:00
feat: Add SeniorCoder and update prompts
This commit is contained in:
parent
095bae6513
commit
087dbb40a3
7 changed files with 40 additions and 204 deletions
|
@ -3,6 +3,7 @@ from .base_coder import Coder
|
|||
from .editblock_coder import EditBlockCoder
|
||||
from .editblock_fenced_coder import EditBlockFencedCoder
|
||||
from .help_coder import HelpCoder
|
||||
from .senior_coder import SeniorCoder
|
||||
|
||||
# from .single_wholefile_func_coder import SingleWholeFileFunctionCoder
|
||||
from .udiff_coder import UnifiedDiffCoder
|
||||
|
@ -17,4 +18,5 @@ __all__ = [
|
|||
WholeFileCoder,
|
||||
UnifiedDiffCoder,
|
||||
# SingleWholeFileFunctionCoder,
|
||||
SeniorCoder,
|
||||
]
|
||||
|
|
|
@ -1187,6 +1187,7 @@ class Coder:
|
|||
self.cur_messages += [dict(role="assistant", content=content)]
|
||||
return
|
||||
|
||||
self.reply_completed()
|
||||
edited = self.apply_updates()
|
||||
|
||||
self.update_cur_messages()
|
||||
|
@ -1238,6 +1239,9 @@ class Coder:
|
|||
else:
|
||||
self.reflected_message = add_rel_files_message
|
||||
|
||||
def reply_completed(self):
|
||||
pass
|
||||
|
||||
def show_exhausted_error(self):
|
||||
output_tokens = 0
|
||||
if self.partial_response_content:
|
||||
|
|
|
@ -1,166 +1,16 @@
|
|||
# flake8: noqa: E501
|
||||
|
||||
from .base_prompts import CoderPrompts
|
||||
from .editblock_prompts import EditBlockPrompts
|
||||
|
||||
|
||||
class EditBlockPrompts(CoderPrompts):
|
||||
class JuniorEditBlockPrompts(EditBlockPrompts):
|
||||
main_system = """Act as an expert software developer who edits source code.
|
||||
{lazy_prompt}
|
||||
Describe each change with a *SEARCH/REPLACE block* per the examples below.
|
||||
All changes to files must use this *SEARCH/REPLACE block* format.
|
||||
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
||||
{shell_cmd_prompt}
|
||||
"""
|
||||
|
||||
shell_cmd_prompt = """
|
||||
4. *Concisely* suggest any shell commands the user might want to run in ```bash blocks.
|
||||
|
||||
Just suggest shell commands this way, not example code.
|
||||
Only suggest complete shell commands that area ready to execute, without placeholders.
|
||||
Only suggest at most a few shell commands at a time, not more than 1-3.
|
||||
|
||||
Use the appropriate shell based on the user's system info:
|
||||
{platform}
|
||||
Examples of when to suggest shell commands:
|
||||
|
||||
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
|
||||
- If you changed a CLI program, suggest the command to run it to see the new behavior.
|
||||
- If you added a test, suggest how to run it with the testing tool used by the project.
|
||||
- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations.
|
||||
- If your code changes add new dependencies, suggest the command to install them.
|
||||
- Etc.
|
||||
"""
|
||||
|
||||
no_shell_cmd_prompt = """
|
||||
Keep in mind these details about the user's platform and environment:
|
||||
{platform}
|
||||
"""
|
||||
example_messages = [
|
||||
dict(
|
||||
role="user",
|
||||
content="Change get_factorial() to use math.factorial",
|
||||
),
|
||||
dict(
|
||||
role="assistant",
|
||||
content="""
|
||||
mathweb/flask/app.py
|
||||
{fence[0]}python
|
||||
<<<<<<< SEARCH
|
||||
from flask import Flask
|
||||
=======
|
||||
import math
|
||||
from flask import Flask
|
||||
>>>>>>> REPLACE
|
||||
{fence[1]}
|
||||
|
||||
mathweb/flask/app.py
|
||||
{fence[0]}python
|
||||
<<<<<<< SEARCH
|
||||
def factorial(n):
|
||||
"compute factorial"
|
||||
|
||||
if n == 0:
|
||||
return 1
|
||||
else:
|
||||
return n * factorial(n-1)
|
||||
|
||||
=======
|
||||
>>>>>>> REPLACE
|
||||
{fence[1]}
|
||||
|
||||
mathweb/flask/app.py
|
||||
{fence[0]}python
|
||||
<<<<<<< SEARCH
|
||||
return str(factorial(n))
|
||||
=======
|
||||
return str(math.factorial(n))
|
||||
>>>>>>> REPLACE
|
||||
{fence[1]}
|
||||
""",
|
||||
),
|
||||
dict(
|
||||
role="user",
|
||||
content="Refactor hello() into its own file.",
|
||||
),
|
||||
dict(
|
||||
role="assistant",
|
||||
content="""
|
||||
hello.py
|
||||
{fence[0]}python
|
||||
<<<<<<< SEARCH
|
||||
=======
|
||||
def hello():
|
||||
"print a greeting"
|
||||
|
||||
print("hello")
|
||||
>>>>>>> REPLACE
|
||||
{fence[1]}
|
||||
|
||||
main.py
|
||||
{fence[0]}python
|
||||
<<<<<<< SEARCH
|
||||
def hello():
|
||||
"print a greeting"
|
||||
|
||||
print("hello")
|
||||
=======
|
||||
from hello import hello
|
||||
>>>>>>> REPLACE
|
||||
{fence[1]}
|
||||
""",
|
||||
),
|
||||
]
|
||||
|
||||
system_reminder = """# *SEARCH/REPLACE block* Rules:
|
||||
|
||||
Every *SEARCH/REPLACE block* must use this format:
|
||||
1. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc.
|
||||
2. The opening fence and code language, eg: {fence[0]}python
|
||||
3. The start of search block: <<<<<<< SEARCH
|
||||
4. A contiguous chunk of lines to search for in the existing source code
|
||||
5. The dividing line: =======
|
||||
6. The lines to replace into the source code
|
||||
7. The end of the replace block: >>>>>>> REPLACE
|
||||
8. The closing fence: {fence[1]}
|
||||
|
||||
Use the *FULL* file path, as shown to you by the user.
|
||||
|
||||
Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
|
||||
If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.
|
||||
|
||||
*SEARCH/REPLACE* blocks will replace *all* matching occurrences.
|
||||
Include enough lines to make the SEARCH blocks uniquely match the lines to change.
|
||||
|
||||
Keep *SEARCH/REPLACE* blocks concise.
|
||||
Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file.
|
||||
Include just the changing lines, and a few surrounding lines if needed for uniqueness.
|
||||
Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.
|
||||
|
||||
Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat!
|
||||
|
||||
To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location.
|
||||
|
||||
Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file.
|
||||
|
||||
If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
|
||||
- A new file path, including dir name if needed
|
||||
- An empty `SEARCH` section
|
||||
- The new file's contents in the `REPLACE` section
|
||||
|
||||
To rename files which have been added to the chat, use shell commands at the end of your response.
|
||||
|
||||
{lazy_prompt}
|
||||
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
||||
{shell_cmd_reminder}
|
||||
"""
|
||||
|
||||
shell_cmd_reminder = """
|
||||
Examples of when to suggest shell commands:
|
||||
|
||||
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
|
||||
- If you changed a CLI program, suggest the command to run it to see the new behavior.
|
||||
- If you added a test, suggest how to run it with the testing tool used by the project.
|
||||
- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations.
|
||||
- If your code changes add new dependencies, suggest the command to install them.
|
||||
- Etc.
|
||||
"""
|
||||
shell_cmd_prompt = ""
|
||||
no_shell_cmd_prompt = ""
|
||||
shell_cmd_reminder = ""
|
||||
|
|
|
@ -1,55 +1,10 @@
|
|||
# flake8: noqa: E501
|
||||
|
||||
from .base_prompts import CoderPrompts
|
||||
from .wholefile_prompts import WholeFilePrompts
|
||||
|
||||
|
||||
class WholeFilePrompts(CoderPrompts):
|
||||
class WholeFilePrompts(WholeFilePrompts):
|
||||
main_system = """Act as an expert software developer and make changes to source code.
|
||||
{lazy_prompt}
|
||||
Output a copy of each file that needs changes.
|
||||
"""
|
||||
|
||||
example_messages = [
|
||||
dict(
|
||||
role="user",
|
||||
content="Change the greeting to be more casual",
|
||||
),
|
||||
dict(
|
||||
role="assistant",
|
||||
content="""
|
||||
show_greeting.py
|
||||
{fence[0]}
|
||||
import sys
|
||||
|
||||
def greeting(name):
|
||||
print(f"Hey {{name}}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
greeting(sys.argv[1])
|
||||
{fence[1]}
|
||||
""",
|
||||
),
|
||||
]
|
||||
|
||||
system_reminder = """You MUST return the entire content of the updated file.
|
||||
You MUST use this *file listing* format:
|
||||
|
||||
path/to/filename.js
|
||||
{fence[0]}
|
||||
// entire file content ...
|
||||
// ... goes in between
|
||||
{fence[1]}
|
||||
|
||||
Every *file listing* MUST use this format:
|
||||
- First line: the filename with any originally provided path
|
||||
- Second line: opening {fence[0]}
|
||||
- ... entire content of the file ...
|
||||
- Final line: closing {fence[1]}
|
||||
|
||||
*NEVER* skip, omit or elide content from a *file listing* using "..." or by adding comments like "... rest of code..."!
|
||||
Create a new file you MUST return a *file listing* which includes an appropriate filename, including any appropriate path.
|
||||
|
||||
{lazy_prompt}
|
||||
"""
|
||||
|
||||
redacted_edit_message = "No changes are needed."
|
||||
|
|
|
@ -1,7 +1,25 @@
|
|||
from aider.models import Model
|
||||
|
||||
from .ask_coder import AskCoder
|
||||
from .base_coder import Coder
|
||||
from .senior_prompts import SeniorPrompts
|
||||
|
||||
|
||||
class SeniorCoder(AskCoder):
|
||||
edit_format = "senior"
|
||||
gpt_prompts = SeniorPrompts()
|
||||
|
||||
def reply_completed(self):
|
||||
content = self.partial_response_content
|
||||
|
||||
kwargs = dict(self.original_kwargs)
|
||||
kwargs["edit_format"] = self.main_model.junior_edit_format
|
||||
kwargs["suggest_shell_commands"] = False
|
||||
|
||||
junior_coder = Coder.create(
|
||||
main_model=Model(self.main_model.junior_model_name),
|
||||
io=self.io,
|
||||
**kwargs,
|
||||
)
|
||||
junior_coder.run(with_message=content, preproc=False)
|
||||
self.move_back_cur_messages("I made those changes to the files.")
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
from .base_prompts import CoderPrompts
|
||||
|
||||
|
||||
class AskPrompts(CoderPrompts):
|
||||
class SeniorPrompts(CoderPrompts):
|
||||
main_system = """Act as an expert senior engineer and provide direction to your junior engineer.
|
||||
Study the change request and the current code.
|
||||
Describe how to modify the code to complete the request.
|
||||
Explain all needed code changes clearly and completely, but concisely.
|
||||
The junior engineer will rely solely on your instructions, so make them unambiguous and complete.
|
||||
Explain all needed code changes clearly and completely, but concisely.
|
||||
Just show the changes needed.
|
||||
|
||||
DO NOT show the entire updated function/file/etc!
|
||||
|
||||
Always reply in the same language as the change request.
|
||||
"""
|
||||
|
|
|
@ -81,6 +81,8 @@ class ModelSettings:
|
|||
use_system_prompt: bool = True
|
||||
use_temperature: bool = True
|
||||
streaming: bool = True
|
||||
junior_model_name: Optional[str] = None
|
||||
junior_edit_format: Optional[str] = None
|
||||
|
||||
|
||||
# https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo
|
||||
|
@ -259,6 +261,8 @@ MODEL_SETTINGS = [
|
|||
"claude-3-5-sonnet-20240620",
|
||||
"diff",
|
||||
weak_model_name="claude-3-haiku-20240307",
|
||||
junior_model_name="claude-3-haiku-20240307",
|
||||
junior_edit_format="whole",
|
||||
use_repo_map=True,
|
||||
examples_as_sys_msg=True,
|
||||
accepts_images=True,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue