Coverage for autogpt/agent/agent_manager.py: 13%
69 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-22 05:45 +0000
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-22 05:45 +0000
1"""Agent manager for managing GPT agents"""
2from __future__ import annotations
4from typing import List, Union
6from autogpt.config.config import Config, Singleton
7from autogpt.llm_utils import create_chat_completion
8from autogpt.types.openai import Message
11class AgentManager(metaclass=Singleton):
12 """Agent manager for managing GPT agents"""
14 def __init__(self):
15 self.next_key = 0
16 self.agents = {} # key, (task, full_message_history, model)
17 self.cfg = Config()
19 # Create new GPT agent
20 # TODO: Centralise use of create_chat_completion() to globally enforce token limit
22 def create_agent(self, task: str, prompt: str, model: str) -> tuple[int, str]:
23 """Create a new agent and return its key
25 Args:
26 task: The task to perform
27 prompt: The prompt to use
28 model: The model to use
30 Returns:
31 The key of the new agent
32 """
33 messages: List[Message] = [
34 {"role": "user", "content": prompt},
35 ]
36 for plugin in self.cfg.plugins:
37 if not plugin.can_handle_pre_instruction():
38 continue
39 if plugin_messages := plugin.pre_instruction(messages):
40 messages.extend(iter(plugin_messages))
41 # Start GPT instance
42 agent_reply = create_chat_completion(
43 model=model,
44 messages=messages,
45 )
47 messages.append({"role": "assistant", "content": agent_reply})
49 plugins_reply = ""
50 for i, plugin in enumerate(self.cfg.plugins):
51 if not plugin.can_handle_on_instruction():
52 continue
53 if plugin_result := plugin.on_instruction(messages):
54 sep = "\n" if i else ""
55 plugins_reply = f"{plugins_reply}{sep}{plugin_result}"
57 if plugins_reply and plugins_reply != "":
58 messages.append({"role": "assistant", "content": plugins_reply})
59 key = self.next_key
60 # This is done instead of len(agents) to make keys unique even if agents
61 # are deleted
62 self.next_key += 1
64 self.agents[key] = (task, messages, model)
66 for plugin in self.cfg.plugins:
67 if not plugin.can_handle_post_instruction():
68 continue
69 agent_reply = plugin.post_instruction(agent_reply)
71 return key, agent_reply
73 def message_agent(self, key: str | int, message: str) -> str:
74 """Send a message to an agent and return its response
76 Args:
77 key: The key of the agent to message
78 message: The message to send to the agent
80 Returns:
81 The agent's response
82 """
83 task, messages, model = self.agents[int(key)]
85 # Add user message to message history before sending to agent
86 messages.append({"role": "user", "content": message})
88 for plugin in self.cfg.plugins:
89 if not plugin.can_handle_pre_instruction():
90 continue
91 if plugin_messages := plugin.pre_instruction(messages):
92 for plugin_message in plugin_messages:
93 messages.append(plugin_message)
95 # Start GPT instance
96 agent_reply = create_chat_completion(
97 model=model,
98 messages=messages,
99 )
101 messages.append({"role": "assistant", "content": agent_reply})
103 plugins_reply = agent_reply
104 for i, plugin in enumerate(self.cfg.plugins):
105 if not plugin.can_handle_on_instruction():
106 continue
107 if plugin_result := plugin.on_instruction(messages):
108 sep = "\n" if i else ""
109 plugins_reply = f"{plugins_reply}{sep}{plugin_result}"
110 # Update full message history
111 if plugins_reply and plugins_reply != "":
112 messages.append({"role": "assistant", "content": plugins_reply})
114 for plugin in self.cfg.plugins:
115 if not plugin.can_handle_post_instruction():
116 continue
117 agent_reply = plugin.post_instruction(agent_reply)
119 return agent_reply
121 def list_agents(self) -> list[tuple[str | int, str]]:
122 """Return a list of all agents
124 Returns:
125 A list of tuples of the form (key, task)
126 """
128 # Return a list of agent keys and their tasks
129 return [(key, task) for key, (task, _, _) in self.agents.items()]
131 def delete_agent(self, key: str | int) -> bool:
132 """Delete an agent from the agent manager
134 Args:
135 key: The key of the agent to delete
137 Returns:
138 True if successful, False otherwise
139 """
141 try:
142 del self.agents[int(key)]
143 return True
144 except KeyError:
145 return False