action_parser.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import re
  2. from opendevin.controller.action_parser import ActionParser
  3. from opendevin.events.action import (
  4. Action,
  5. AgentFinishAction,
  6. CmdRunAction,
  7. IPythonRunCellAction,
  8. MessageAction,
  9. )
  10. class CodeActSWEActionParserFinish(ActionParser):
  11. """
  12. Parser action:
  13. - AgentFinishAction() - end the interaction
  14. """
  15. def __init__(
  16. self,
  17. ):
  18. self.finish_command = None
  19. def check_condition(self, action_str: str) -> bool:
  20. self.finish_command = re.search(r'<finish>.*</finish>', action_str, re.DOTALL)
  21. return self.finish_command is not None
  22. def parse(self, action_str: str) -> Action:
  23. assert (
  24. self.finish_command is not None
  25. ), 'self.finish_command should not be None when parse is called'
  26. thought = action_str.replace(self.finish_command.group(0), '').strip()
  27. return AgentFinishAction(thought=thought)
  28. class CodeActSWEActionParserCmdRun(ActionParser):
  29. """
  30. Parser action:
  31. - CmdRunAction(command) - bash command to run
  32. - AgentFinishAction() - end the interaction
  33. """
  34. def __init__(
  35. self,
  36. ):
  37. self.bash_command = None
  38. def check_condition(self, action_str: str) -> bool:
  39. self.bash_command = re.search(
  40. r'<execute_bash>(.*?)</execute_bash>', action_str, re.DOTALL
  41. )
  42. return self.bash_command is not None
  43. def parse(self, action_str: str) -> Action:
  44. assert (
  45. self.bash_command is not None
  46. ), 'self.bash_command should not be None when parse is called'
  47. thought = action_str.replace(self.bash_command.group(0), '').strip()
  48. # a command was found
  49. command_group = self.bash_command.group(1).strip()
  50. if command_group.strip() == 'exit':
  51. return AgentFinishAction()
  52. return CmdRunAction(command=command_group, thought=thought)
  53. class CodeActSWEActionParserIPythonRunCell(ActionParser):
  54. """
  55. Parser action:
  56. - IPythonRunCellAction(code) - IPython code to run
  57. """
  58. def __init__(
  59. self,
  60. ):
  61. self.python_code = None
  62. self.jupyter_kernel_init_code: str = 'from agentskills import *'
  63. def check_condition(self, action_str: str) -> bool:
  64. self.python_code = re.search(
  65. r'<execute_ipython>(.*?)</execute_ipython>', action_str, re.DOTALL
  66. )
  67. return self.python_code is not None
  68. def parse(self, action_str: str) -> Action:
  69. assert (
  70. self.python_code is not None
  71. ), 'self.python_code should not be None when parse is called'
  72. code_group = self.python_code.group(1).strip()
  73. thought = action_str.replace(self.python_code.group(0), '').strip()
  74. return IPythonRunCellAction(
  75. code=code_group,
  76. thought=thought,
  77. kernel_init_code=self.jupyter_kernel_init_code,
  78. )
  79. class CodeActSWEActionParserMessage(ActionParser):
  80. """
  81. Parser action:
  82. - MessageAction(content) - Message action to run (e.g. ask for clarification)
  83. """
  84. def __init__(
  85. self,
  86. ):
  87. pass
  88. def check_condition(self, action_str: str) -> bool:
  89. # We assume the LLM is GOOD enough that when it returns pure natural language
  90. # it wants to talk to the user
  91. return True
  92. def parse(self, action_str: str) -> Action:
  93. return MessageAction(content=action_str, wait_for_response=True)