agent.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from jinja2 import BaseLoader, Environment
  2. from agenthub.micro.instructions import instructions
  3. from 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.serialization.action import action_from_dict
  11. from openhands.events.serialization.event import event_to_memory
  12. from openhands.llm.llm import LLM
  13. from openhands.memory.history import ShortTermHistory
  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(
  27. self, history: ShortTermHistory, max_events: int = 20, **kwargs
  28. ):
  29. """
  30. Serialize and simplify history to str format
  31. """
  32. processed_history = []
  33. event_count = 0
  34. for event in history.get_events(reverse=True):
  35. if event_count >= max_events:
  36. break
  37. processed_history.append(
  38. event_to_memory(event, self.llm.config.max_message_chars)
  39. )
  40. event_count += 1
  41. # history is in reverse order, let's fix it
  42. processed_history.reverse()
  43. return json.dumps(processed_history, **kwargs)
  44. def __init__(self, llm: LLM, config: AgentConfig):
  45. super().__init__(llm, config)
  46. if 'name' not in self.agent_definition:
  47. raise ValueError('Agent definition must contain a name')
  48. self.prompt_template = Environment(loader=BaseLoader).from_string(self.prompt)
  49. self.delegates = all_microagents.copy()
  50. del self.delegates[self.agent_definition['name']]
  51. def step(self, state: State) -> Action:
  52. last_user_message, last_image_urls = state.get_current_user_intent()
  53. prompt = self.prompt_template.render(
  54. state=state,
  55. instructions=instructions,
  56. to_json=to_json,
  57. history_to_json=self.history_to_json,
  58. delegates=self.delegates,
  59. latest_user_message=last_user_message,
  60. )
  61. content = [TextContent(text=prompt)]
  62. if self.llm.vision_is_active() and last_image_urls:
  63. content.append(ImageContent(image_urls=last_image_urls))
  64. message = Message(role='user', content=content)
  65. resp = self.llm.completion(
  66. messages=self.llm.format_messages_for_llm(message),
  67. )
  68. action_resp = resp['choices'][0]['message']['content']
  69. action = parse_response(action_resp)
  70. return action