Skip to content

Commit efb7833

Browse files
committed
Support "c" response during command execution.
1 parent b62e71d commit efb7833

File tree

1 file changed

+110
-59
lines changed

1 file changed

+110
-59
lines changed

babyagi.py

Lines changed: 110 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@
104104
# Run configuration
105105
INSTANCE_NAME = os.getenv("INSTANCE_NAME", os.getenv("BABY_NAME", "BabyCommandAGI"))
106106
COOPERATIVE_MODE = "none"
107-
# If USER_INPUT_LLM is set to True, the LLM will automatically respond if there is a confirmation when executing a command,
107+
# If LLM_COMMAND_RESPONSE is set to True, the LLM will automatically respond if there is a confirmation when executing a command,
108108
# but be aware that this will increase the number of times the LLM is used and increase the cost of the API, etc.
109-
USER_INPUT_LLM = True
109+
LLM_COMMAND_RESPONSE = True
110110
JOIN_EXISTING_OBJECTIVE = False
111111
MAX_OUTPUT_TOKEN = 4 * 1024 # It seems that the maximum output is 4K. 'max_tokens is too large: 64000. This model supports at most 4096 completion tokens, whereas you provided 64000.'
112112
MAX_INPUT_TOKEN = 128 * 1024 - MAX_OUTPUT_TOKEN - 200 # 200 is the length of the fixed text added at the end.
@@ -614,12 +614,12 @@ def check_input():
614614
global input_flag
615615
while True:
616616
time.sleep(2)
617-
if input_flag == 'f':
617+
if input_flag == "f" or input_flag == "c":
618618
continue
619619
log("\n" + "\033[33m\033[1m" + 'The state has been set so that if you input "f", it will go to feedback.' + "\033[0m\033[0m" + "\n")
620620
inp = input()
621-
if inp == 'f':
622-
input_flag = 'f'
621+
if inp == "f" or inp == "c":
622+
input_flag = inp
623623

624624
# Thread for non-blocking input check
625625
input_thread = threading.Thread(target=check_input, daemon=True)
@@ -1430,15 +1430,22 @@ def execution_command(objective: str, command: str, task_list: deque,
14301430
notification_time = time.time()
14311431
print("\n" + "\033[33m\033[1m" + '"f": go to "feedback"' + "\033[0m\033[0m" + "\n")
14321432

1433+
result = ""
1434+
end_prcessing = False
1435+
wait_input = False
1436+
14331437
while process.poll() is None:
14341438

1435-
if input_flag == 'f':
1436-
log("\n" + "\033[33m\033[1m" + 'The "f" is pressed and it goes to "feedback".' + "\033[0m\033[0m" + "\n")
1437-
return 'BabyCommandAGI: Complete'
1438-
14391439
if notification_time + 30 < time.time():
14401440
notification_time = time.time()
1441-
print("\n" + "\033[33m\033[1m" + '"f": go to "feedback"' + "\033[0m\033[0m" + "\n")
1441+
if end_prcessing:
1442+
end_prcessing = False
1443+
wait_input = False
1444+
else:
1445+
if wait_input:
1446+
print("\n" + "\033[33m\033[1m" + 'Force termination of the process. Please enter "c".' + "\033[0m\033[0m" + "\n")
1447+
else:
1448+
print("\n" + "\033[33m\033[1m" + '"f": go to "feedback". Since the process is running, you can respond by typing "c".' + "\033[0m\033[0m" + "\n")
14421449

14431450
# Check for output with a timeout of some minutes
14441451
rlist, wlist, xlist = select.select([pty_master], [], [], 2)
@@ -1448,8 +1455,8 @@ def execution_command(objective: str, command: str, task_list: deque,
14481455
std_blocks.extend(list_std_blocks(xlist))
14491456

14501457
else:
1451-
if USER_INPUT_LLM:
1452-
if time.time() - start_time > 300:
1458+
if LLM_COMMAND_RESPONSE:
1459+
if time.time() - start_time > 300 and result == "":
14531460
start_time = time.time()
14541461

14551462
# Concatenate the output and split it by lines
@@ -1458,37 +1465,82 @@ def execution_command(objective: str, command: str, task_list: deque,
14581465
# No output received within 5 seconds, call the check_wating_for_response function with the last 3 lines or the entire content
14591466
lastlines = stdout_lines[-3:] if len(stdout_lines) >= 3 else stdout_lines
14601467
lastlines = "\n".join(lastlines)
1461-
input = user_input_for_waiting(objective, lastlines, command,
1468+
llm_command_response = llm_command_response_for_waiting(objective, lastlines, command,
14621469
"".join(std_blocks), task_list,
14631470
executed_task_list, current_dir)
1464-
if input.startswith('BabyCommandAGI: Complete'):
1465-
return input
1466-
elif input.startswith('BabyCommandAGI: Interruption'):
1467-
break
1468-
elif input.startswith('BabyCommandAGI: Continue'):
1471+
if llm_command_response.startswith('BabyCommandAGI: Complete'):
1472+
result = 'Waiting for user feedback'
1473+
elif llm_command_response.startswith('BabyCommandAGI: Interruption'):
1474+
result = 'The command was interrupted by BabyCommandAGI'
1475+
elif llm_command_response.startswith('BabyCommandAGI: Continue'):
14691476
pass
14701477
else:
1471-
input += '\n'
1472-
os.write(pty_master, input.encode())
1478+
llm_command_response += '\n'
1479+
os.write(pty_master, llm_command_response.encode())
1480+
1481+
if input_flag == "f":
1482+
result = 'Waiting for user feedback'
1483+
1484+
if result != "":
1485+
if input_flag is None:
1486+
if wait_input == False:
1487+
wait_input = True
1488+
log("\n" + "\033[33m\033[1m" + 'Force termination of the process. Please enter "c".' + "\033[0m\033[0m" + "\n")
1489+
continue
1490+
1491+
if end_prcessing:
1492+
continue
1493+
log("\n" + "\033[33m\033[1m" + 'Force termination of the process. If the process requires a response such as termination, enter the response. If it is not necessary, leave it empty and press [Enter].' + "\033[0m\033[0m" + "\n")
1494+
response = input()
1495+
if response == "":
1496+
break
1497+
response += '\n'
1498+
os.write(pty_master, response.encode())
1499+
end_prcessing = True
1500+
notification_time = time.time()
1501+
start_time = time.time()
1502+
1503+
if input_flag == "c":
1504+
input_flag = None
1505+
1506+
elif input_flag == "c":
1507+
log("\n" + "\033[33m\033[1m" + 'Please enter your response.' + "\033[0m\033[0m" + "\n")
1508+
response = input()
1509+
response += '\n'
1510+
os.write(pty_master, response.encode())
1511+
notification_time = time.time()
1512+
start_time = time.time()
1513+
input_flag = None
1514+
14731515

1474-
os.close(pty_master)
1475-
pty_master = None
14761516
out = "".join(std_blocks)
14771517

1478-
with open("/tmp/cmd_exit_status", "r") as status_file:
1479-
cmd_exit_status = int(status_file.read().strip())
1518+
if input_flag == "f":
1519+
result = 'Waiting for user feedback'
1520+
1521+
if result == "":
1522+
with open("/tmp/cmd_exit_status", "r") as status_file:
1523+
cmd_exit_status = int(status_file.read().strip())
14801524

1481-
result = f"The Return Code for the command is {cmd_exit_status}:\n{out}"
1525+
result = f"The Return Code for the command is {cmd_exit_status}"
1526+
1527+
all_result = f"{result}:\n{out}"
1528+
result = all_result
14821529

14831530
log("\n" + "\033[33m\033[1m" + "[[Output]]" + "\033[0m\033[0m" + "\n\n" +
14841531
result + "\n\n")
14851532
finally:
1533+
os.close(pty_master)
1534+
pty_master = None
14861535
process.terminate()
14871536
process.wait()
1537+
if input_flag == "c":
1538+
input_flag = None
1539+
14881540

14891541
return result
14901542

1491-
def user_input_for_waiting(objective: str, lastlines: str, command: str,
1543+
def llm_command_response_for_waiting(objective: str, lastlines: str, command: str,
14921544
all_output_for_command: str, task_list: deque,
14931545
executed_task_list: deque, current_dir: str) -> str:
14941546
prompt = f"""You are an expert in shell commands to achieve the "{objective}".
@@ -1593,14 +1645,8 @@ def user_feedback() -> str:
15931645
response = input()
15941646
log('\n')
15951647

1596-
# If the objective has been achieved
1597-
if response.lower() == 'y':
1598-
return 'y'
1599-
1600-
# If the objective has not been achieved
1601-
else:
1602-
log("\033[33m\033[1m" + "[[Feedback]]" + "\n\n" + response + "\033[0m\033[0m" + "\n")
1603-
return response
1648+
log("\033[33m\033[1m" + "[[Feedback]]" + "\n\n" + response + "\033[0m\033[0m" + "\n")
1649+
return response
16041650

16051651
def check_first_two_lines_same_comment_style(text):
16061652
"""
@@ -1636,7 +1682,7 @@ def check_first_two_lines_same_comment_style(text):
16361682

16371683
pty_master = None
16381684

1639-
def main():
1685+
def execute_objective():
16401686
global OBJECTIVE
16411687
global input_flag
16421688

@@ -1850,7 +1896,7 @@ def main():
18501896

18511897
enriched_result = { "type": "command", "target": command, "path": current_dir}
18521898

1853-
if all_result.startswith("BabyCommandAGI: Complete"):
1899+
if all_result.startswith("Waiting for user feedback"):
18541900
enriched_result['result'] = result #"Success"
18551901
executed_tasks_storage.appendleft(enriched_result)
18561902
save_data(executed_tasks_storage.get_tasks(), EXECUTED_TASK_LIST_FILE)
@@ -1928,30 +1974,35 @@ def main():
19281974
time.sleep(1)
19291975

19301976
log("\033[92m\033[1m" + "*****COMPLETE*****\n\n" + "\033[0m\033[0m")
1931-
while True:
1932-
if input_flag != "f":
1933-
log("\n" + "\033[33m\033[1m" + 'If the OBJECTIVE has not been achieved, please input "f". The AI will continue to execute based on the feedback.' + "\033[0m\033[0m" + "\n")
1934-
while True:
1935-
time.sleep(1)
1936-
if input_flag == "f":
1937-
break
1938-
feedback = user_feedback()
1939-
enriched_result = {
1940-
"type": "feedback",
1941-
"target": "user",
1942-
"result": feedback
1943-
}
1944-
executed_tasks_storage.appendleft(enriched_result)
1945-
save_data(executed_tasks_storage.get_tasks(), EXECUTED_TASK_LIST_FILE)
1946-
1947-
objective_list = deque([feedback, ORIGINAL_OBJECTIVE])
1948-
save_data(objective_list, OBJECTIVE_LIST_FILE)
1949-
OBJECTIVE = parse_objective(objective_list)
1950-
tasks_storage.appendleft({"type": "plan", "content": feedback})
1951-
save_data(tasks_storage.get_tasks(), TASK_LIST_FILE)
1977+
1978+
if input_flag != "f":
19521979
input_flag = None
1953-
main()
1954-
break
1980+
log("\n" + "\033[33m\033[1m" + 'If the OBJECTIVE has not been achieved, please input "f". The AI will continue to execute based on the feedback.' + "\033[0m\033[0m" + "\n")
1981+
while True:
1982+
time.sleep(1)
1983+
if input_flag == "f":
1984+
break
1985+
elif input_flag is not None:
1986+
input_flag = None
1987+
feedback = user_feedback()
1988+
enriched_result = {
1989+
"type": "feedback",
1990+
"target": "user",
1991+
"result": feedback
1992+
}
1993+
executed_tasks_storage.appendleft(enriched_result)
1994+
save_data(executed_tasks_storage.get_tasks(), EXECUTED_TASK_LIST_FILE)
1995+
1996+
objective_list = deque([feedback, ORIGINAL_OBJECTIVE])
1997+
save_data(objective_list, OBJECTIVE_LIST_FILE)
1998+
OBJECTIVE = parse_objective(objective_list)
1999+
tasks_storage.appendleft({"type": "plan", "content": feedback})
2000+
save_data(tasks_storage.get_tasks(), TASK_LIST_FILE)
2001+
input_flag = None
2002+
2003+
def main():
2004+
while True:
2005+
execute_objective()
19552006

19562007
if __name__ == "__main__":
19572008
main()

0 commit comments

Comments
 (0)