agent.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. from jinja2 import BaseLoader, Environment
  2. from openhands.agenthub.micro.instructions import instructions
  3. from openhands.agenthub.micro.registry import all_microagents
  4. from openhands.controller.agent import Agent
  5. from openhands.controller.state.state import State
  6. from openhands.core.config import AgentConfig
  7. from openhands.core.message import ImageContent, Message, TextContent
  8. from openhands.core.utils import json
  9. from openhands.events.action import Action
  10. from openhands.events.event import Event
  11. from openhands.events.serialization.action import action_from_dict
  12. from openhands.events.serialization.event import event_to_memory
  13. from openhands.llm.llm import LLM
  14. def parse_response(orig_response: str) -> Action:
  15. # attempt to load the JSON dict from the response
  16. action_dict = json.loads(orig_response)
  17. # load the action from the dict
  18. return action_from_dict(action_dict)
  19. def to_json(obj, **kwargs):
  20. """Serialize an object to str format"""
  21. return json.dumps(obj, **kwargs)
  22. class MicroAgent(Agent):
  23. VERSION = '1.0'
  24. prompt = ''
  25. agent_definition: dict = {}
  26. def history_to_json(self, history: list[Event], max_events: int = 20, **kwargs):
  27. """
  28. Serialize and simplify history to str format
  29. """
  30. processed_history = []
  31. event_count = 0
  32. for event in reversed(history):
  33. if event_count >= max_events:
  34. break
  35. processed_history.append(
  36. event_to_memory(event, self.llm.config.max_message_chars)
  37. )
  38. event_count += 1
  39. # history is in reverse order, let's fix it
  40. processed_history.reverse()
  41. return json.dumps(processed_history, **kwargs)
  42. def __init__(self, llm: LLM, config: AgentConfig):
  43. super().__init__(llm, config)
  44. if 'name' not in self.agent_definition:
  45. raise ValueError('Agent definition must contain a name')
  46. self.prompt_template = Environment(loader=BaseLoader).from_string(self.prompt)
  47. self.delegates = all_microagents.copy()
  48. del self.delegates[self.agent_definition['name']]
  49. def step(self, state: State) -> Action:
  50. last_user_message, last_image_urls = state.get_current_user_intent()
  51. prompt = self.prompt_template.render(
  52. state=state,
  53. instructions=instructions,
  54. to_json=to_json,
  55. history_to_json=self.history_to_json,
  56. delegates=self.delegates,
  57. latest_user_message=last_user_message,
  58. )
  59. content = [TextContent(text=prompt)]
  60. if self.llm.vision_is_active() and last_image_urls:
  61. content.append(ImageContent(image_urls=last_image_urls))
  62. message = Message(role='user', content=content)
  63. resp = self.llm.completion(
  64. messages=self.llm.format_messages_for_llm(message),
  65. )
  66. action_resp = resp['choices'][0]['message']['content']
  67. action = parse_response(action_resp)
  68. return action