agent.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. from typing import Optional
  2. from opendevin.const.guide_url import TROUBLESHOOTING_URL
  3. from opendevin.controller import AgentController
  4. from opendevin.controller.agent import Agent
  5. from opendevin.core.config import config
  6. from opendevin.core.logger import opendevin_logger as logger
  7. from opendevin.core.schema import ActionType, AgentState, ConfigType
  8. from opendevin.events.action import (
  9. ChangeAgentStateAction,
  10. NullAction,
  11. action_from_dict,
  12. )
  13. from opendevin.events.event import Event
  14. from opendevin.events.observation import (
  15. NullObservation,
  16. )
  17. from opendevin.events.stream import EventSource, EventStream, EventStreamSubscriber
  18. from opendevin.llm.llm import LLM
  19. from opendevin.server.session import session_manager
  20. class AgentUnit:
  21. """Represents a session with an agent.
  22. Attributes:
  23. controller: The AgentController instance for controlling the agent.
  24. """
  25. sid: str
  26. event_stream: EventStream
  27. controller: Optional[AgentController] = None
  28. # TODO: we will add the runtime here
  29. # runtime: Optional[Runtime] = None
  30. def __init__(self, sid):
  31. """Initializes a new instance of the Session class."""
  32. self.sid = sid
  33. self.event_stream = EventStream()
  34. self.event_stream.subscribe(EventStreamSubscriber.SERVER, self.on_event)
  35. async def send_error(self, message):
  36. """Sends an error message to the client.
  37. Args:
  38. message: The error message to send.
  39. """
  40. await session_manager.send_error(self.sid, message)
  41. async def send_message(self, message):
  42. """Sends a message to the client.
  43. Args:
  44. message: The message to send.
  45. """
  46. await session_manager.send_message(self.sid, message)
  47. async def send(self, data):
  48. """Sends data to the client.
  49. Args:
  50. data: The data to send.
  51. """
  52. await session_manager.send(self.sid, data)
  53. async def dispatch(self, action: str | None, data: dict):
  54. """Dispatches actions to the agent from the client."""
  55. if action is None:
  56. await self.send_error('Invalid action')
  57. return
  58. if action == ActionType.INIT:
  59. await self.create_controller(data)
  60. await self.event_stream.add_event(
  61. ChangeAgentStateAction(AgentState.INIT), EventSource.USER
  62. )
  63. return
  64. elif action == ActionType.START:
  65. if self.controller is None:
  66. await self.send_error('No agent started.')
  67. return
  68. task = data['args']['task']
  69. await self.controller.setup_task(task)
  70. await self.event_stream.add_event(
  71. ChangeAgentStateAction(agent_state=AgentState.RUNNING), EventSource.USER
  72. )
  73. return
  74. action_dict = data.copy()
  75. action_dict['action'] = action
  76. action_obj = action_from_dict(action_dict)
  77. await self.event_stream.add_event(action_obj, EventSource.USER)
  78. async def create_controller(self, start_event: dict):
  79. """Creates an AgentController instance.
  80. Args:
  81. start_event: The start event data (optional).
  82. """
  83. args = {
  84. key: value
  85. for key, value in start_event.get('args', {}).items()
  86. if value != ''
  87. } # remove empty values, prevent FE from sending empty strings
  88. agent_cls = args.get(ConfigType.AGENT, config.agent.name)
  89. model = args.get(ConfigType.LLM_MODEL, config.llm.model)
  90. api_key = args.get(ConfigType.LLM_API_KEY, config.llm.api_key)
  91. api_base = config.llm.base_url
  92. max_iterations = args.get(ConfigType.MAX_ITERATIONS, config.max_iterations)
  93. max_chars = args.get(ConfigType.MAX_CHARS, config.llm.max_chars)
  94. logger.info(f'Creating agent {agent_cls} using LLM {model}')
  95. llm = LLM(model=model, api_key=api_key, base_url=api_base)
  96. if self.controller is not None:
  97. await self.controller.close()
  98. try:
  99. self.controller = AgentController(
  100. sid=self.sid,
  101. event_stream=self.event_stream,
  102. agent=Agent.get_cls(agent_cls)(llm),
  103. max_iterations=int(max_iterations),
  104. max_chars=int(max_chars),
  105. )
  106. except Exception as e:
  107. logger.exception(f'Error creating controller: {e}')
  108. await self.send_error(
  109. f'Error creating controller. Please check Docker is running and visit `{TROUBLESHOOTING_URL}` for more debugging information..'
  110. )
  111. return
  112. async def on_event(self, event: Event):
  113. """Callback function for agent events.
  114. Args:
  115. event: The agent event (Observation or Action).
  116. """
  117. if event.source == 'agent' and not isinstance(event, (NullAction, NullObservation)):
  118. await self.send(event.to_dict())
  119. return
  120. def close(self):
  121. if self.controller is not None:
  122. self.controller.close()