gpt-4 recommended renaming process_name as command_id and changing format in prompt

This commit is contained in:
Nicholas Albion
2023-10-14 00:24:11 +11:00
parent ca8782dee5
commit 185a9cd4fa
6 changed files with 43 additions and 40 deletions

View File

@@ -44,7 +44,7 @@ def command_definition(description_command='A single command that needs to be ex
description_timeout=
'Timeout in milliseconds that represent the approximate time this command takes to finish. '
'If you need to run a command that doesnt\'t finish by itself (eg. a command to run an app), '
'set the timeout to to a value long enough to determine that it has started successfully and provide a process_name. '
'set the timeout to to a value long enough to determine that it has started successfully and provide a command_id. '
'If you need to create a directory that doesn\'t exist and is not the root project directory, '
'always create it by running a command `mkdir`'):
return {
@@ -63,10 +63,10 @@ def command_definition(description_command='A single command that needs to be ex
'type': 'string',
'description': 'A message to look for in the output of the command to determine if successful or not.',
},
'process_name': {
'command_id': {
'type': 'string',
'description': 'If the process needs to continue running after the command is executed provide '
'a name which you can use to kill the process later.',
'a unique command identifier which you can use to kill the process later.',
}
},
'required': ['command', 'timeout'],
@@ -193,7 +193,7 @@ IMPLEMENT_TASK = {
'command': command_definition(),
'kill_process': {
'type': 'string',
'description': 'To kill a process that was left running by a previous `command` step provide the `process_name` in this field and set `type` to "kill_process".',
'description': 'To kill a process that was left running by a previous `command` step provide the `command_id` in this field and set `type` to "kill_process".',
},
'code_change': {
'type': 'object',

View File

@@ -103,12 +103,12 @@ class Developer(Agent):
# TODO END
additional_message = 'Let\'s start with the step #0:\n\n' if i == 0 else f'So far, steps { ", ".join(f"#{j}" for j in range(i)) } are finished so let\'s do step #{i + 1} now.\n\n'
process_name = data['process_name'] if 'process_name' in data else None
command_id = data['command_id'] if 'command_id' in data else None
success_message = data['success_message'] if 'success_message' in data else None
return run_command_until_success(convo, data['command'],
timeout=data['timeout'],
process_name=process_name,
command_id=command_id,
success_message=success_message,
additional_message=additional_message)
@@ -136,7 +136,7 @@ class Developer(Agent):
cbs={
'r': lambda conv: run_command_until_success(conv,
self.run_command,
process_name='app',
command_id='app',
timeout=None,
force=True,
return_cli_response=True)
@@ -328,7 +328,7 @@ class Developer(Agent):
response = self.project.ask_for_human_intervention(
user_description,
cbs={'r': lambda convo: run_command_until_success(convo, self.run_command,
process_name='app',
command_id='app',
timeout=None,
force=True,
return_cli_response=True, is_root_task=True)},

View File

@@ -18,7 +18,7 @@ from const.code_execution import MIN_COMMAND_RUN_TIME, MAX_COMMAND_RUN_TIME, MAX
interrupted = False
running_processes: Dict[str, tuple[str, int]] = {}
"""Holds a list of (command, process ID)s, mapped to the `process_name` provided in the call to `execute_command()`."""
"""Holds a list of (command, process ID)s, mapped to the `command_id` provided in the call to `execute_command()`."""
def enqueue_output(out, q):
@@ -72,14 +72,14 @@ def run_command(command, root_path, q_stdout, q_stderr) -> subprocess.Popen:
return process
def terminate_named_process(process_name: str) -> None:
if process_name in running_processes:
terminate_process(running_processes[process_name][1], process_name)
def terminate_named_process(command_id: str) -> None:
if command_id in running_processes:
terminate_process(running_processes[command_id][1], command_id)
def terminate_running_processes():
for process_name in list(running_processes.keys()):
terminate_process(running_processes[process_name][1], process_name)
for command_id in list(running_processes.keys()):
terminate_process(running_processes[command_id][1], command_id)
def terminate_process(pid: int, name=None) -> None:
@@ -99,12 +99,12 @@ def terminate_process(pid: int, name=None) -> None:
except OSError as e:
logger.error(f'Error while terminating process: {e}')
for process_name in list(running_processes.keys()):
if running_processes[process_name][1] == pid:
del running_processes[process_name]
for command_id in list(running_processes.keys()):
if running_processes[command_id][1] == pid:
del running_processes[command_id]
def execute_command(project, command, timeout=None, success_message=None, process_name: str = None, force=False) \
def execute_command(project, command, timeout=None, success_message=None, command_id: str = None, force=False) \
-> (str, str, int):
"""
Execute a command and capture its output.
@@ -114,8 +114,7 @@ def execute_command(project, command, timeout=None, success_message=None, proces
command (str): The command to run.
timeout (int, optional): The maximum execution time in milliseconds. Default is None.
success_message: A message to look for in the output of the command to determine if successful or not.
process_name (str, optional): A name for the process.
If `timeout` is not provided, can be used to terminate the process.
command_id (str, optional): A unique identifier assigned by the LLM, can be used to terminate the process.
force (bool, optional): Whether to execute the command without confirmation. Default is False.
Returns:
@@ -178,9 +177,9 @@ def execute_command(project, command, timeout=None, success_message=None, proces
q = queue.Queue()
process = run_command(command, project.root_path, q, q_stderr)
if process_name is not None:
terminate_named_process(process_name)
running_processes[process_name] = (command, process.pid)
if command_id is not None:
terminate_named_process(command_id)
running_processes[command_id] = (command, process.pid)
output = ''
stderr_output = ''
@@ -213,8 +212,8 @@ def execute_command(project, command, timeout=None, success_message=None, proces
# If timeout is reached, kill the process
if timeout is not None and elapsed_time * 1000 > timeout:
if process_name is not None:
logger.info(f'Process "{process_name}" running after timeout as pid: {process.pid}')
if command_id is not None:
logger.info(f'Process "{command_id}" running after timeout as pid: {process.pid}')
break
raise TimeoutError("Command exceeded the specified timeout.")
@@ -340,7 +339,7 @@ def execute_command_and_check_cli_response(command, timeout, convo):
def run_command_until_success(convo, command,
timeout: Union[int, None],
process_name: Union[str, None] = None,
command_id: Union[str, None] = None,
success_message=None,
additional_message=None,
force=False,
@@ -353,7 +352,7 @@ def run_command_until_success(convo, command,
convo (AgentConvo): The conversation object.
command (str): The command to run.
timeout (int): The maximum execution time in milliseconds.
process_name: A name for the process.
command_id: A name for the process.
If `timeout` is not provided, can be used to terminate the process.
success_message: A message to look for in the output of the command to determine if successful or not.
additional_message (str, optional): Additional message to include in the response.
@@ -365,7 +364,7 @@ def run_command_until_success(convo, command,
command,
timeout=timeout,
success_message=success_message,
process_name=process_name,
command_id=command_id,
force=force)
if response is None:
@@ -398,7 +397,7 @@ def run_command_until_success(convo, command,
return convo.agent.debugger.debug(convo, {
'command': command,
'timeout': timeout,
'process_name': process_name,
'command_id': command_id,
'success_message': success_message,
})
except TooDeepRecursionError as e:

View File

@@ -3,10 +3,12 @@ The project directory tree looks like:
{{ directory_tree }}
{% endif -%}
{%- if running_processes %}
{% if running_processes -%}
Note that the following processes are already running:
{% for key, data in running_processes.items() -%}
- "{{ key }}" (`{{ data[0] }}`)
{% endfor -%}
{% endif -%}
{%- for key, data in running_processes.items() %}
command_id: {{ key }}
command: {{ data[0] }}
{%- endfor -%}
{%- endif -%}

View File

@@ -1,8 +1,10 @@
Ok, now, take your previous message and convert it to actionable items. An item might be a code change or a command run. When you need to change code, make sure that you put the entire content of the file in the value of `content` key even though you will likely copy and paste the most of the previous message. Note that the commands will run on a {{ os }} machine.
{%- if running_processes %}
{% if running_processes -%}
Note that the following processes are already running:
{% for key, data in running_processes.items() -%}
- "{{ key }}" (`{{ data[0] }}`)
{% endfor -%}
{% endif -%}
{%- for key, data in running_processes.items() %}
command_id: {{ key }}
command: {{ data[0] }}
{%- endfor -%}
{%- endif -%}

View File

@@ -66,4 +66,4 @@ def test_parse_task_with_processes():
# Then
assert 'the following processes are already running:' in prompt
assert '- "app" (`npm start`)\n- "mongo" (`mongod`)' in prompt
assert 'command_id: app\ncommand: npm start\n\ncommand_id: mongo\ncommand: mongod' in prompt