Skip to content

Commit

Permalink
fix(prompts): minor fixes and improvements to prompts
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikBjare committed Dec 7, 2024
1 parent 83736d6 commit 10108a1
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 62 deletions.
10 changes: 6 additions & 4 deletions gptme/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def prompt_gptme(interactive: bool) -> Generator[Message, None, None]:

base_prompt = f"""
You are gptme v{__version__}, a general-purpose AI assistant powered by LLMs.
You are designed to help users with programming tasks, such as writing code, debugging and learning new concepts.
You are designed to help users with programming tasks, such as writing code, debugging, and learning new concepts.
You can run code, execute terminal commands, and access the filesystem on the local machine.
You will help the user with writing code, either from scratch or in existing projects.
You will think step by step when solving a problem, in `<thinking>` tags.
Expand All @@ -106,7 +106,7 @@ def prompt_gptme(interactive: bool) -> Generator[Message, None, None]:
- provide a corrected response
You should learn about the context needed to provide the best help,
such as exploring a potential project in the current working directory and reading the code using terminal tools.
such as exploring the current working directory and reading the code using terminal tools.
When suggesting code changes, prefer applying patches over examples. Preserve comments, unless they are no longer relevant.
Use the patch tool to edit existing files, or the save tool to overwrite.
Expand All @@ -122,7 +122,7 @@ def prompt_gptme(interactive: bool) -> Generator[Message, None, None]:
Maintain a professional and efficient communication style. Be concise but thorough in your explanations.
Think before you answer, in `<thinking>` tags.
Use `<thinking>` tags to think before you answer.
""".strip()

interactive_prompt = """
Expand Down Expand Up @@ -271,5 +271,7 @@ def get_workspace_prompt(workspace: Path) -> str:
document_prompt_function(interactive=True)(prompt_gptme)
document_prompt_function()(prompt_user)
document_prompt_function()(prompt_project)
document_prompt_function()(prompt_tools)
document_prompt_function(tool_format="markdown")(prompt_tools)
# document_prompt_function(tool_format="xml")(prompt_tools)
# document_prompt_function(tool_format="tool")(prompt_tools)
document_prompt_function()(prompt_systeminfo)
20 changes: 12 additions & 8 deletions gptme/tools/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from ..codeblock import Codeblock
from ..message import Message
from ..util import transform_examples_to_chat_directives
from ..util import clean_example, transform_examples_to_chat_directives

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -221,21 +221,25 @@ def get_tool_prompt(self, examples: bool, tool_format: ToolFormat):
instructions = self.get_instructions(tool_format)
if instructions:
prompt += f"\n\n**Instructions:** {instructions}"
if examples and (examples_content := self.get_examples(tool_format)):
if examples and (
examples_content := self.get_examples(tool_format, quote=True).strip()
):
prompt += f"\n\n### Examples\n\n{examples_content}"
return prompt

def get_examples(self, tool_format: ToolFormat = "markdown"):
def get_examples(self, tool_format: ToolFormat = "markdown", quote=False):
if callable(self.examples):
return self.examples(tool_format)
return self.examples
examples = self.examples(tool_format)
else:
examples = self.examples
# make sure headers have exactly two newlines after them
examples = re.sub(r"\n*(\n#+.*?)\n+", r"\n\1\n\n", examples)
return clean_example(examples, quote=quote)

def get_functions_description(self) -> str:
# return a prompt with a brief description of the available functions
if self.functions:
description = (
"The following Python functions can be called with `ipython` tool:\n\n"
)
description = "This tool makes the following Python functions available in `ipython`:\n\n"
return description + "\n".join(
f"{callable_signature(func)}: {func.__doc__ or 'No description'}"
for func in self.functions
Expand Down
2 changes: 1 addition & 1 deletion gptme/tools/gh.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def examples(tool_format):
{ToolUse("shell", [], '''
REPO=$(basename $(pwd))
gh repo create $REPO --public --source . --push
''').to_output(tool_format)}
'''.strip()).to_output(tool_format)}
> User: show issues
> Assistant:
Expand Down
26 changes: 17 additions & 9 deletions gptme/tools/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
Parameter,
ToolSpec,
ToolUse,
callable_signature,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -140,13 +141,15 @@ def get_installed_python_libraries() -> set[str]:


def get_functions():
return "\n".join([f"- {func.__name__}" for func in registered_functions.values()])
return "\n".join(
[f"- {callable_signature(func)}" for func in registered_functions.values()]
)


instructions = """
This tool execute Python code in an interactive IPython session.
Use this tool to execute Python code in an interactive IPython session.
It will respond with the output and result of the execution.
"""
""".strip()

instructions_format = {
"markdown": """
Expand All @@ -158,16 +161,18 @@ def get_functions():

def examples(tool_format):
return f"""
#### Results of the last expression will be displayed, IPython-style:
#### Result of the last expression will be returned
> User: What is 2 + 2?
> Assistant:
{ToolUse("ipython", [], "2 + 2").to_output(tool_format)}
> System: Executed code block.
{ToolUse("result", [], "4").to_output()}
#### It can write an example and then execute it:
#### Write a function and call it
> User: compute fib 10
> Assistant: To compute the 10th Fibonacci number, we can execute this code:
> Assistant: To compute the 10th Fibonacci number, we can run the following code:
{ToolUse("ipython", [], '''
def fib(n):
if n <= 1:
Expand All @@ -182,14 +187,17 @@ def fib(n):

def init() -> ToolSpec:
python_libraries = get_installed_python_libraries()
python_libraries_str = "\n".join(f"- {lib}" for lib in python_libraries)
python_libraries_str = (
"\n".join(f"- {lib}" for lib in python_libraries)
or "- no common libraries found"
)

_instructions = f"""{instructions}
The following libraries are available:
Available libraries:
{python_libraries_str}
The following functions are available:
Available functions:
{get_functions()}
""".strip()

Expand Down
6 changes: 3 additions & 3 deletions gptme/tools/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

def examples(tool_format):
return f"""
User: read file.txt
Assistant:
> User: read file.txt
> Assistant:
{ToolUse("shell", [], "cat file.txt").to_output(tool_format)}
"""
""".strip()


# Note: this isn't actually a tool, it only serves prompting purposes
Expand Down
3 changes: 2 additions & 1 deletion gptme/tools/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@
def examples(tool_format):
return f"""
> User: write a hello world script to hello.py
> Assistant:
{ToolUse("save", ["hello.py"], 'print("Hello world")').to_output(tool_format)}
> System: Saved to `hello.py`
> User: make it all-caps
> Assistant:
{ToolUse("save", ["hello.py"], 'print("HELLO WORLD")').to_output(tool_format)}
> System: Saved to `hello.py`
""".strip()
Expand Down
30 changes: 16 additions & 14 deletions gptme/tools/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,43 +64,45 @@

def examples(tool_format):
return f"""
User: list the current directory
Assistant: To list the files in the current directory, use `ls`:
> User: list the current directory
> Assistant: To list the files in the current directory, use `ls`:
{ToolUse("shell", [], "ls").to_output(tool_format)}
System: Ran command: `ls`
> System: Ran command: `ls`
{ToolUse("shell", [], '''
file1.txt
file2.txt
'''.strip()).to_output()}
#### The assistant can learn context by exploring the filesystem
User: learn about the project
Assistant: Lets start by checking the files
> User: learn about the project
> Assistant: Lets start by checking the files
{ToolUse("shell", [], "git ls-files").to_output(tool_format)}
System:
> System:
{ToolUse("stdout", [], '''
README.md
main.py
'''.strip()).to_output()}
Assistant: Now lets check the README
> Assistant: Now lets check the README
{ToolUse("shell", [], "cat README.md").to_output(tool_format)}
System:
> System:
{ToolUse("stdout", [], "(contents of README.md)").to_output()}
Assistant: Now we check main.py
> Assistant: Now we check main.py
{ToolUse("shell", [], "cat main.py").to_output(tool_format)}
System:
> System:
{ToolUse("stdout", [], "(contents of main.py)").to_output()}
Assistant: The project is...
> Assistant: The project is...
#### Create vue project
User: Create a new vue project with typescript and pinia named fancy-project
Assistant: Sure! Let's create a new vue project with TypeScript and Pinia named fancy-project:
> User: Create a new vue project with typescript and pinia named fancy-project
> Assistant: Sure! Let's create a new vue project with TypeScript and Pinia named fancy-project:
{ToolUse("shell",
[],
"npm init vue@latest fancy-project --yes -- --typescript --pinia"
).to_output()}
System:
> System:
{ToolUse("stdout", [], '''
> npx
> create-vue
Expand Down
44 changes: 24 additions & 20 deletions gptme/tools/tmux.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,43 +213,47 @@ def execute_tmux(
def examples(tool_format):
all_examples = f"""
#### Managing a dev server
User: Start the dev server
Assistant: Certainly! To start the dev server we should use tmux:
> User: Start the dev server
> Assistant: Certainly! To start the dev server we should use tmux:
{ToolUse("tmux", [], "new_session 'npm run dev'").to_output(tool_format)}
System: Running `npm run dev` in session 0
> System: Running `npm run dev` in session 0
User: Can you show me the current content of the pane?
Assistant: Of course! Let's inspect the pane content:
> User: Can you show me the current content of the pane?
> Assistant: Of course! Let's inspect the pane content:
{ToolUse("tmux", [], "inspect_pane 0").to_output(tool_format)}
System:
> System:
{ToolUse("output", [], "Server is running on localhost:5600").to_output()}
User: Stop the dev server
Assistant: I'll send 'Ctrl+C' to the pane to stop the server:
> User: Stop the dev server
> Assistant: I'll send 'Ctrl+C' to the pane to stop the server:
{ToolUse("tmux", [], "send_keys 0 C-c").to_output(tool_format)}
System: Sent 'C-c' to pane 0
> System: Sent 'C-c' to pane 0
#### Get info from ncurses applications
User: start top and give me a summary
Assistant: Sure! Let's start the top command in a tmux session:
> User: start top and give me a summary
> Assistant: Sure! Let's start the top command in a tmux session:
{ToolUse("tmux", [], "new_session 'top'").to_output(tool_format)}
System: Running `top` in session 1.
> System: Running `top` in session 1.
{ToolUse("output", [], "(output from top shown here)").to_output()}
Assistant: The load is...
> Assistant: The load is...
#### Background process
User: Start the dev server
Assistant: Certainly! To start the dev server we should use the tmux tool to run it in a tmux session:
> User: Start the dev server
> Assistant: Certainly! To start the dev server we should use the tmux tool to run it in a tmux session:
{ToolUse("tmux", [], "new_session 'npm run dev'").to_output(tool_format)}
#### Ending a session
User: I changed my mind
Assistant: No problem! Let's kill the session and start over:
> User: I changed my mind
> Assistant: No problem! Let's kill the session and start over:
{ToolUse("tmux", [], "list_session 0").to_output(tool_format)}
System: Active tmux sessions [0]
Assistant:
> System: Active tmux sessions [0]
> Assistant:
{ToolUse("tmux", [], "kill_session 0").to_output(tool_format)}
System: Killed tmux session with ID 0
> System: Killed tmux session with ID 0
"""
# we want to skip the last two examples in prompting
return "####".join(all_examples.split("####")[:-2])
Expand Down
4 changes: 2 additions & 2 deletions gptme/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ def epoch_to_age(epoch, incl_date=False):
)


def clean_example(s: str, strict=False) -> str:
def clean_example(s: str, strict=False, quote=False) -> str:
orig = s
s = re.sub(
r"(^|\n)([>] )?([A-Za-z]+):",
r"\1\3:",
rf"\1{'> ' if quote else ''}\3:",
s,
)
if strict:
Expand Down

0 comments on commit 10108a1

Please sign in to comment.