Rename fields in agent metadata (#336)

* Rename fields in agent metadata

* team one fixes

* another fix
This commit is contained in:
Jack Gerrits
2024-08-07 16:08:13 -04:00
committed by GitHub
parent 437dbefc32
commit 39489ba395
32 changed files with 94 additions and 95 deletions

View File

@@ -29,7 +29,7 @@ import tiktoken
from agnext.components.models import AssistantMessage
encoding = None
encoding = None
def count_token(value: str) -> int:
# TODO:: Migrate to model_client.count_tokens
global encoding
@@ -40,7 +40,7 @@ def count_token(value: str) -> int:
async def response_preparer(task: str, source: str, client: ChatCompletionClient, transcript: List[LLMMessage]) -> str:
messages: List[LLMMessage] = []
# copy them to this context
# copy them to this context
for message in transcript:
messages.append(
UserMessage(
@@ -168,7 +168,7 @@ async def main() -> None:
run_context = runtime.start()
actual_surfer = await runtime.try_get_underlying_agent_instance(web_surfer.id, type=MultimodalWebSurfer)
actual_surfer = await runtime.try_get_underlying_agent_instance(web_surfer.id, type=MultimodalWebSurfer)
await actual_surfer.init(model_client=client, downloads_folder=os.getcwd(), browser_channel="chromium")
#await runtime.send_message(RequestReplyMessage(), user_proxy.id)
@@ -206,7 +206,7 @@ async def main() -> None:
# Output the final answer
actual_orchestrator = await runtime.try_get_underlying_agent_instance(orchestrator.id, type=LedgerOrchestrator)
transcript: List[LLMMessage] = actual_orchestrator._chat_history # type: ignore
print(await response_preparer(task=task, source=(await orchestrator.metadata)["name"], client=client, transcript=transcript))
print(await response_preparer(task=task, source=(await orchestrator.metadata)["type"], client=client, transcript=transcript))

View File

@@ -100,7 +100,7 @@ If the code has executed successfully, and the problem is stolved, reply "TERMIN
)
assert isinstance(response.content, str)
self._session_memory[session_id].append(
AssistantMessage(content=response.content, source=self.metadata["name"])
AssistantMessage(content=response.content, source=self.metadata["type"])
)
await self.publish_message(
@@ -138,7 +138,7 @@ If the code has executed successfully, and the problem is stolved, reply "TERMIN
)
assert isinstance(response.content, str)
self._session_memory[message.session_id].append(
AssistantMessage(content=response.content, source=self.metadata["name"])
AssistantMessage(content=response.content, source=self.metadata["type"])
)
if "TERMINATE" in response.content:

View File

@@ -56,7 +56,7 @@ class MyAgent(TypeRoutedAgent):
await self.publish_message(
TextMessage(
content=f"I received a message from {message.source}. Message received #{self._received_count}",
source=self.metadata["name"],
source=self.metadata["type"],
)
)

View File

@@ -175,7 +175,7 @@ class ChatCompletionAgent(TypeRoutedAgent):
# Get a response from the model.
hisorical_messages = await self._memory.get_messages()
response = await self._client.create(
self._system_messages + convert_messages_to_llm_messages(hisorical_messages, self.metadata["name"]),
self._system_messages + convert_messages_to_llm_messages(hisorical_messages, self.metadata["type"]),
tools=self._tools,
json_output=response_format == ResponseFormat.json_object,
)
@@ -190,14 +190,14 @@ class ChatCompletionAgent(TypeRoutedAgent):
):
# Send a function call message to itself.
response = await self.send_message(
message=FunctionCallMessage(content=response.content, source=self.metadata["name"]),
message=FunctionCallMessage(content=response.content, source=self.metadata["type"]),
recipient=self.id,
cancellation_token=cancellation_token,
)
# Make an assistant message from the response.
hisorical_messages = await self._memory.get_messages()
response = await self._client.create(
self._system_messages + convert_messages_to_llm_messages(hisorical_messages, self.metadata["name"]),
self._system_messages + convert_messages_to_llm_messages(hisorical_messages, self.metadata["type"]),
tools=self._tools,
json_output=response_format == ResponseFormat.json_object,
)
@@ -205,10 +205,10 @@ class ChatCompletionAgent(TypeRoutedAgent):
final_response: Message
if isinstance(response.content, str):
# If the response is a string, return a text message.
final_response = TextMessage(content=response.content, source=self.metadata["name"])
final_response = TextMessage(content=response.content, source=self.metadata["type"])
elif isinstance(response.content, list) and all(isinstance(x, FunctionCall) for x in response.content):
# If the response is a list of function calls, return a function call message.
final_response = FunctionCallMessage(content=response.content, source=self.metadata["name"])
final_response = FunctionCallMessage(content=response.content, source=self.metadata["type"])
else:
raise ValueError(f"Unexpected response: {response.content}")

View File

@@ -63,7 +63,7 @@ class ImageGenerationAgent(TypeRoutedAgent):
messages = await self._memory.get_messages()
if len(messages) == 0:
return MultiModalMessage(
content=["I need more information to generate an image."], source=self.metadata["name"]
content=["I need more information to generate an image."], source=self.metadata["type"]
)
prompt = ""
for m in messages:
@@ -74,5 +74,5 @@ class ImageGenerationAgent(TypeRoutedAgent):
assert len(response.data) > 0 and response.data[0].b64_json is not None
# Create a MultiModalMessage with the image.
image = Image.from_base64(response.data[0].b64_json)
multi_modal_message = MultiModalMessage(content=[image], source=self.metadata["name"])
multi_modal_message = MultiModalMessage(content=[image], source=self.metadata["type"])
return multi_modal_message

View File

@@ -121,7 +121,7 @@ class OpenAIAssistantAgent(TypeRoutedAgent):
raise ValueError(f"Expected text content in the last message: {last_message_content}")
# TODO: handle multiple text content.
return TextMessage(content=text_content[0].text.value, source=self.metadata["name"])
return TextMessage(content=text_content[0].text.value, source=self.metadata["type"])
def save_state(self) -> Mapping[str, Any]:
return {

View File

@@ -23,7 +23,7 @@ class UserProxyAgent(TypeRoutedAgent):
async def on_publish_now(self, message: PublishNow, cancellation_token: CancellationToken) -> None:
"""Handle a publish now message. This method prompts the user for input, then publishes it."""
user_input = await self.get_user_input(self._user_input_prompt)
await self.publish_message(TextMessage(content=user_input, source=self.metadata["name"]))
await self.publish_message(TextMessage(content=user_input, source=self.metadata["type"]))
async def get_user_input(self, prompt: str) -> str:
"""Get user input from the console. Override this method to customize how user input is retrieved."""

View File

@@ -23,11 +23,11 @@ async def select_speaker(memory: ChatMemory[Message], client: ChatCompletionClie
# Construct agent roles.
roles = "\n".join(
[f"{(await agent.metadata)['name']}: {(await agent.metadata)['description']}".strip() for agent in agents]
[f"{(await agent.metadata)['type']}: {(await agent.metadata)['description']}".strip() for agent in agents]
)
# Construct agent list.
participants = str([(await agent.metadata)["name"] for agent in agents])
participants = str([(await agent.metadata)["type"] for agent in agents])
# Select the next speaker.
select_speaker_prompt = f"""You are in a role play game. The following roles are available:
@@ -48,7 +48,7 @@ Read the above conversation. Then select the next role from {participants} to pl
# Get the index of the selected agent by name
agent_index = 0
for i, agent in enumerate(agents):
if (await agent.metadata)["name"] == agent_name:
if (await agent.metadata)["type"] == agent_name:
agent_index = i
break
@@ -74,7 +74,7 @@ async def mentioned_agents(message_content: str, agents: List[AgentProxy]) -> Di
for agent in agents:
# Finds agent mentions, taking word boundaries into account,
# accommodates escaping underscores and underscores as spaces
name = (await agent.metadata)["name"]
name = (await agent.metadata)["type"]
regex = (
r"(?<=\W)("
+ re.escape(name)

View File

@@ -73,7 +73,7 @@ Some additional points to consider:
# Send the task specs to the orchestrator and specialists.
for agent in [*self._specialists, self._orchestrator]:
await (await self.send_message(TextMessage(content=task_specs, source=self.metadata["name"]), agent))
await (await self.send_message(TextMessage(content=task_specs, source=self.metadata["type"]), agent))
# Inner loop.
stalled_turns = 0
@@ -85,7 +85,7 @@ Some additional points to consider:
if data["is_request_satisfied"]["answer"]:
return TextMessage(
content=f"The task has been successfully addressed. {data['is_request_satisfied']['reason']}",
source=self.metadata["name"],
source=self.metadata["type"],
)
# Update stalled turns.
@@ -111,7 +111,7 @@ Some additional points to consider:
if educated_guess["has_educated_guesses"]["answer"]:
return TextMessage(
content=f"The task is addressed with an educated guess. {educated_guess['has_educated_guesses']['reason']}",
source=self.metadata["name"],
source=self.metadata["type"],
)
# Come up with a new plan.
@@ -129,7 +129,7 @@ Some additional points to consider:
for agent in [*self._specialists, self._orchestrator]:
_ = await (
await self.send_message(
TextMessage(content=subtask, source=self.metadata["name"]),
TextMessage(content=subtask, source=self.metadata["type"]),
agent,
)
)
@@ -161,7 +161,7 @@ Some additional points to consider:
return TextMessage(
content="The task was not addressed. The maximum number of turns was reached.",
source=self.metadata["name"],
source=self.metadata["type"],
)
async def _prepare_task(self, task: str, sender: str) -> Tuple[str, str, str, str]:

View File

@@ -27,7 +27,7 @@ class Inner(TypeRoutedAgent):
@message_handler()
async def on_new_message(self, message: MessageType, cancellation_token: CancellationToken) -> MessageType:
return MessageType(body=f"Inner: {message.body}", sender=self.metadata["name"])
return MessageType(body=f"Inner: {message.body}", sender=self.metadata["type"])
class Outer(TypeRoutedAgent):
@@ -40,7 +40,7 @@ class Outer(TypeRoutedAgent):
inner_response = self.send_message(message, self._inner)
inner_message = await inner_response
assert isinstance(inner_message, MessageType)
return MessageType(body=f"Outer: {inner_message.body}", sender=self.metadata["name"])
return MessageType(body=f"Outer: {inner_message.body}", sender=self.metadata["type"])
async def main() -> None:

View File

@@ -63,13 +63,13 @@ class ChatCompletionAgent(TypeRoutedAgent):
return
llm_messages: List[LLMMessage] = []
for m in self._memory[-10:]:
if m.source == self.metadata["name"]:
llm_messages.append(AssistantMessage(content=m.content, source=self.metadata["name"]))
if m.source == self.metadata["type"]:
llm_messages.append(AssistantMessage(content=m.content, source=self.metadata["type"]))
else:
llm_messages.append(UserMessage(content=m.content, source=m.source))
response = await self._model_client.create(self._system_messages + llm_messages)
assert isinstance(response.content, str)
await self.publish_message(Message(content=response.content, source=self.metadata["name"]))
await self.publish_message(Message(content=response.content, source=self.metadata["type"]))
async def main() -> None:

View File

@@ -108,7 +108,7 @@ class UserProxyAgent(TypeRoutedAgent): # type: ignore
return
else:
# Publish user input and exit handler.
await self.publish_message(TextMessage(content=user_input, source=self.metadata["name"]))
await self.publish_message(TextMessage(content=user_input, source=self.metadata["type"]))
return

View File

@@ -60,13 +60,13 @@ Use the following JSON format to provide your thought on the latest message and
# Get a response from the model.
raw_response = await self._client.create(
self._system_messages
+ convert_messages_to_llm_messages(await self._memory.get_messages(), self_name=self.metadata["name"]),
+ convert_messages_to_llm_messages(await self._memory.get_messages(), self_name=self.metadata["type"]),
json_output=True,
)
assert isinstance(raw_response.content, str)
# Save the response to memory.
await self._memory.add_message(TextMessage(source=self.metadata["name"], content=raw_response.content))
await self._memory.add_message(TextMessage(source=self.metadata["type"], content=raw_response.content))
# Parse the response.
data = json.loads(raw_response.content)
@@ -75,7 +75,7 @@ Use the following JSON format to provide your thought on the latest message and
# Publish the response if needed.
if respond is True or str(respond).lower().strip() == "true":
await self.publish_message(TextMessage(source=self.metadata["name"], content=str(response)))
await self.publish_message(TextMessage(source=self.metadata["type"], content=str(response)))
class ChatRoomUserAgent(TextualUserAgent):

View File

@@ -86,9 +86,9 @@ async def illustrator_critics(runtime: AgentRuntime, app: TextualChatApp) -> Non
app.welcoming_notice = f"""You are now in a group chat with the following agents:
1. 🤖 {(await descriptor.metadata)['name']}: {(await descriptor.metadata).get('description')}
2. 🤖 {(await illustrator.metadata)['name']}: {(await illustrator.metadata).get('description')}
3. 🤖 {(await critic.metadata)['name']}: {(await critic.metadata).get('description')}
1. 🤖 {(await descriptor.metadata)['type']}: {(await descriptor.metadata).get('description')}
2. 🤖 {(await illustrator.metadata)['type']}: {(await illustrator.metadata).get('description')}
3. 🤖 {(await critic.metadata)['type']}: {(await critic.metadata).get('description')}
Provide a prompt for the illustrator to generate an image.
"""

View File

@@ -171,7 +171,7 @@ class TextualUserAgent(TypeRoutedAgent): # type: ignore
# Generate a ramdom file name.
for content in message.content:
if isinstance(content, Image):
filename = f"{self.metadata['name']}_{message.source}_{random.randbytes(16).hex()}.png"
filename = f"{self.metadata['type']}_{message.source}_{random.randbytes(16).hex()}.png"
content.image.save(filename)
await self._app.post_runtime_message(message)

View File

@@ -97,7 +97,7 @@ Reply "TERMINATE" in the end when everything is done."""
response = await self._model_client.create(self._system_messages + self._session_memory[session_id])
assert isinstance(response.content, str)
self._session_memory[session_id].append(
AssistantMessage(content=response.content, source=self.metadata["name"])
AssistantMessage(content=response.content, source=self.metadata["type"])
)
# Publish the code execution task.
@@ -116,7 +116,7 @@ Reply "TERMINATE" in the end when everything is done."""
response = await self._model_client.create(self._system_messages + self._session_memory[message.session_id])
assert isinstance(response.content, str)
self._session_memory[message.session_id].append(
AssistantMessage(content=response.content, source=self.metadata["name"])
AssistantMessage(content=response.content, source=self.metadata["type"])
)
if "TERMINATE" in response.content:

View File

@@ -100,7 +100,7 @@ Please review the code and provide feedback.
"""
# Generate a response using the chat completion API.
response = await self._model_client.create(
self._system_messages + [UserMessage(content=prompt, source=self.metadata["name"])]
self._system_messages + [UserMessage(content=prompt, source=self.metadata["type"])]
)
assert isinstance(response.content, str)
# TODO: use structured generation library e.g. guidance to ensure the response is in the expected format.
@@ -162,7 +162,7 @@ Code: <Your code>
self._session_memory.setdefault(session_id, []).append(message)
# Generate a response using the chat completion API.
response = await self._model_client.create(
self._system_messages + [UserMessage(content=message.task, source=self.metadata["name"])]
self._system_messages + [UserMessage(content=message.task, source=self.metadata["type"])]
)
assert isinstance(response.content, str)
# Extract the code block from the response.

View File

@@ -97,13 +97,13 @@ class GroupChatParticipant(TypeRoutedAgent):
return
llm_messages: List[LLMMessage] = []
for m in self._memory[-10:]:
if m.source == self.metadata["name"]:
llm_messages.append(AssistantMessage(content=m.content, source=self.metadata["name"]))
if m.source == self.metadata["type"]:
llm_messages.append(AssistantMessage(content=m.content, source=self.metadata["type"]))
else:
llm_messages.append(UserMessage(content=m.content, source=m.source))
response = await self._model_client.create(self._system_messages + llm_messages)
assert isinstance(response.content, str)
speach = Message(content=response.content, source=self.metadata["name"])
speach = Message(content=response.content, source=self.metadata["type"])
self._memory.append(speach)
await self.publish_message(speach)

View File

@@ -62,7 +62,7 @@ class ReferenceAgent(TypeRoutedAgent):
@message_handler
async def handle_task(self, message: ReferenceAgentTask, cancellation_token: CancellationToken) -> None:
"""Handle a task message. This method sends the task to the model and publishes the result."""
task_message = UserMessage(content=message.task, source=self.metadata["name"])
task_message = UserMessage(content=message.task, source=self.metadata["type"])
response = await self._model_client.create(self._system_messages + [task_message])
assert isinstance(response.content, str)
task_result = ReferenceAgentTaskResult(session_id=message.session_id, result=response.content)
@@ -100,7 +100,7 @@ class AggregatorAgent(TypeRoutedAgent):
if len(self._session_results[message.session_id]) == self._num_references:
result = "\n\n".join([r.result for r in self._session_results[message.session_id]])
response = await self._model_client.create(
self._system_messages + [UserMessage(content=result, source=self.metadata["name"])]
self._system_messages + [UserMessage(content=result, source=self.metadata["type"])]
)
assert isinstance(response.content, str)
task_result = AggregatorTaskResult(result=response.content)

View File

@@ -94,7 +94,7 @@ class MathSolver(TypeRoutedAgent):
def __init__(self, model_client: ChatCompletionClient, neighbor_names: List[str], max_round: int) -> None:
super().__init__("A debator.")
self._model_client = model_client
if self.metadata["name"] in neighbor_names:
if self.metadata["type"] in neighbor_names:
raise ValueError("The agent's name cannot be in the list of neighbor names.")
self._neighbor_names = neighbor_names
self._memory: Dict[str, List[LLMMessage]] = {}
@@ -153,9 +153,9 @@ class MathSolver(TypeRoutedAgent):
assert isinstance(response.content, str)
# Add the response to the memory.
self._memory[message.session_id].append(
AssistantMessage(content=response.content, source=self.metadata["name"])
AssistantMessage(content=response.content, source=self.metadata["type"])
)
logger.debug(f"Solver {self.metadata['name']} response: {response.content}")
logger.debug(f"Solver {self.metadata['type']} response: {response.content}")
# Extract the answer from the response.
match = re.search(r"\{\{(\-?\d+(\.\d+)?)\}\}", response.content)
if match is None:
@@ -171,7 +171,7 @@ class MathSolver(TypeRoutedAgent):
await self.publish_message(
IntermediateSolverResponse(
content=response.content,
solver_name=self.metadata["name"],
solver_name=self.metadata["type"],
answer=answer,
session_id=message.session_id,
round=self._counters[message.session_id],

View File

@@ -66,7 +66,7 @@ class ToolUseAgent(TypeRoutedAgent):
session: List[LLMMessage] = []
session.append(UserMessage(content=message.content, source="User"))
response = await self._model_client.create(self._system_messages + session, tools=self._tool_schema)
session.append(AssistantMessage(content=response.content, source=self.metadata["name"]))
session.append(AssistantMessage(content=response.content, source=self.metadata["type"]))
# Keep executing the tools until the response is not a list of function calls.
while isinstance(response.content, list) and all(isinstance(item, FunctionCall) for item in response.content):
@@ -89,7 +89,7 @@ class ToolUseAgent(TypeRoutedAgent):
session.append(FunctionExecutionResultMessage(content=function_results))
# Execute the model again with the new response.
response = await self._model_client.create(self._system_messages + session, tools=self._tool_schema)
session.append(AssistantMessage(content=response.content, source=self.metadata["name"]))
session.append(AssistantMessage(content=response.content, source=self.metadata["type"]))
assert isinstance(response.content, str)
return Message(content=response.content)

View File

@@ -121,7 +121,7 @@ class ToolUseAgent(TypeRoutedAgent):
response = await self._model_client.create(
self._system_messages + self._sessions[session_id], tools=self._tools
)
self._sessions[session_id].append(AssistantMessage(content=response.content, source=self.metadata["name"]))
self._sessions[session_id].append(AssistantMessage(content=response.content, source=self.metadata["type"]))
if isinstance(response.content, str):
# If the response is a string, just publish the response.
@@ -163,7 +163,7 @@ class ToolUseAgent(TypeRoutedAgent):
self._system_messages + self._sessions[message.session_id], tools=self._tools
)
self._sessions[message.session_id].append(
AssistantMessage(content=response.content, source=self.metadata["name"])
AssistantMessage(content=response.content, source=self.metadata["type"])
)
# If the response is a string, just publish the response.
if isinstance(response.content, str):

View File

@@ -304,8 +304,7 @@ class SingleThreadedAgentRuntime(AgentRuntime):
sender_agent = (
await self._get_agent(message_envelope.sender) if message_envelope.sender is not None else None
)
# TODO use id
sender_name = sender_agent.metadata["name"] if sender_agent is not None else "Unknown"
sender_name = str(sender_agent.id) if sender_agent is not None else "Unknown"
logger.info(
f"Calling message handler for {agent_id.type} with message type {type(message_envelope.message).__name__} published by {sender_name}"
)

View File

@@ -68,8 +68,8 @@ class ClosureAgent(Agent):
def metadata(self) -> AgentMetadata:
assert self._id is not None
return AgentMetadata(
namespace=self._id.key,
name=self._id.type,
key=self._id.key,
type=self._id.type,
description=self._description,
subscriptions=self._subscriptions,
)

View File

@@ -2,7 +2,7 @@ from typing import Sequence, TypedDict
class AgentMetadata(TypedDict):
name: str
namespace: str
type: str
key: str
description: str
subscriptions: Sequence[str]

View File

@@ -15,8 +15,8 @@ class BaseAgent(ABC, Agent):
def metadata(self) -> AgentMetadata:
assert self._id is not None
return AgentMetadata(
namespace=self._id.key,
name=self._id.type,
key=self._id.key,
type=self._id.type,
description=self._description,
subscriptions=self._subscriptions,
)

View File

@@ -94,7 +94,7 @@ class TeamOneBaseAgent(TypeRoutedAgent):
self._enabled = False
logger.info(
AgentEvent(
f"{self.metadata['name']} (deactivated)",
f"{self.metadata['type']} (deactivated)",
"",
)
)

View File

@@ -40,7 +40,7 @@ class BaseOrchestrator(TeamOneBaseAgent):
if self._num_rounds >= self._max_rounds:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (termination condition)",
f"{self.metadata['type']} (termination condition)",
f"Max rounds ({self._max_rounds}) reached.",
)
)
@@ -49,7 +49,7 @@ class BaseOrchestrator(TeamOneBaseAgent):
if message.request_halt:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (termination condition)",
f"{self.metadata['type']} (termination condition)",
f"{source} requested halt.",
)
)
@@ -59,7 +59,7 @@ class BaseOrchestrator(TeamOneBaseAgent):
if next_agent is None:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (termination condition)",
f"{self.metadata['type']} (termination condition)",
"No agent selected.",
)
)
@@ -69,8 +69,8 @@ class BaseOrchestrator(TeamOneBaseAgent):
logger.info(
OrchestrationEvent(
source=f"{self.metadata['name']} (thought)",
message=f"Next speaker {(await next_agent.metadata)['name']}" "",
source=f"{self.metadata['type']} (thought)",
message=f"Next speaker {(await next_agent.metadata)['type']}" "",
)
)

View File

@@ -41,10 +41,10 @@ class BaseWorker(TeamOneBaseAgent):
"""Respond to a reply request."""
request_halt, response = await self._generate_reply(cancellation_token)
assistant_message = AssistantMessage(content=message_content_to_str(response), source=self.metadata["name"])
assistant_message = AssistantMessage(content=message_content_to_str(response), source=self.metadata["type"])
self._chat_history.append(assistant_message)
user_message = UserMessage(content=response, source=self.metadata["name"])
user_message = UserMessage(content=response, source=self.metadata["type"])
await self.publish_message(BroadcastMessage(content=user_message, request_halt=request_halt))
async def _generate_reply(self, cancellation_token: CancellationToken) -> Tuple[bool, UserContent]:

View File

@@ -211,7 +211,7 @@ setInterval(function() {{
await self._page.screenshot(path=os.path.join(self.debug_dir, "screenshot.png"))
logger.info(
WebSurferEvent(
source=self.metadata["name"],
source=self.metadata["type"],
url=self._page.url,
message="Resetting browser.",
)
@@ -262,7 +262,7 @@ setInterval(function() {{
assert self._page is not None
logger.info(
WebSurferEvent(
source=self.metadata["name"],
source=self.metadata["type"],
url=self._page.url,
action=name,
arguments=args,
@@ -519,7 +519,7 @@ When deciding between tools, consider if the request can be best addressed by:
# Add the multimodal message and make the request
history.append(
UserMessage(content=[text_prompt, AGImage.from_pil(scaled_screenshot)], source=self.metadata["name"])
UserMessage(content=[text_prompt, AGImage.from_pil(scaled_screenshot)], source=self.metadata["type"])
)
response = await self._model_client.create(
history, tools=tools, extra_create_args={"tool_choice": "auto"}
@@ -674,7 +674,7 @@ When deciding between tools, consider if the request can be best addressed by:
logger.info(
WebSurferEvent(
source=self.metadata["name"],
source=self.metadata["type"],
url=self._page.url,
message="New tab or window.",
)
@@ -758,7 +758,7 @@ When deciding between tools, consider if the request can be best addressed by:
prompt + buffer + line,
# ag_image,
# ],
source=self.metadata["name"],
source=self.metadata["type"],
)
remaining = self._model_client.remaining_tokens(messages + [message])
@@ -779,7 +779,7 @@ When deciding between tools, consider if the request can be best addressed by:
prompt + buffer,
ag_image,
],
source=self.metadata["name"],
source=self.metadata["type"],
)
)
@@ -811,7 +811,7 @@ When deciding between tools, consider if the request can be best addressed by:
"Please transcribe all visible text on this page, including both main content and the labels of UI elements.",
AGImage.from_pil(scaled_screenshot),
],
source=self.metadata["name"],
source=self.metadata["type"],
)
)
response = await self._model_client.create(messages)

View File

@@ -83,13 +83,13 @@ class LedgerOrchestrator(BaseOrchestrator):
team_description = ""
for agent in self._agents:
metadata = await agent.metadata
name = metadata["name"]
name = metadata["type"]
description = metadata["description"]
team_description += f"{name}: {description}\n"
return team_description
async def _get_team_names(self) -> List[str]:
return [(await agent.metadata)["name"] for agent in self._agents]
return [(await agent.metadata)["type"] for agent in self._agents]
def _set_task_str(self, message: LLMMessage) -> None:
if len(self._chat_history) == 1:
@@ -119,18 +119,18 @@ class LedgerOrchestrator(BaseOrchestrator):
# create a closed book task and generate a response and update the chat history
cb_task = self._get_closed_book_prompt(self.task_str)
cb_user_message = UserMessage(
content=cb_task, source=self.metadata["name"]
content=cb_task, source=self.metadata["type"]
) # TODO: allow images in this message.
cb_response = await self._model_client.create(self._system_messages + self._chat_history + [cb_user_message])
facts = cb_response.content
assert isinstance(facts, str)
cb_assistant_message = AssistantMessage(content=facts, source=self.metadata["name"])
cb_assistant_message = AssistantMessage(content=facts, source=self.metadata["type"])
# 2. CREATE A PLAN
## plan based on available information
plan_task = self._get_plan_prompt(self.task_str, team_description)
plan_user_message = UserMessage(
content=plan_task, source=self.metadata["name"]
content=plan_task, source=self.metadata["type"]
) # TODO: allow images in this message.
plan_response = await self._model_client.create(
self._system_messages + self._chat_history + [cb_assistant_message, plan_user_message]
@@ -148,7 +148,7 @@ class LedgerOrchestrator(BaseOrchestrator):
team_description = await self._get_team_description()
names = await self._get_team_names()
ledger_prompt = self._get_ledger_prompt(self.task_str, team_description, names)
ledger_user_message = UserMessage(content=ledger_prompt, source=self.metadata["name"])
ledger_user_message = UserMessage(content=ledger_prompt, source=self.metadata["type"])
assert max_json_retries > 0
for _ in range(max_json_retries):
@@ -165,7 +165,7 @@ class LedgerOrchestrator(BaseOrchestrator):
except json.JSONDecodeError as e:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (error)",
f"{self.metadata['type']} (error)",
f"Failed to parse ledger information: {ledger_str}",
)
)
@@ -180,10 +180,10 @@ class LedgerOrchestrator(BaseOrchestrator):
if self._should_replan:
plan_str = await self._plan()
plan_user_message = UserMessage(content=plan_str, source=self.metadata["name"])
plan_user_message = UserMessage(content=plan_str, source=self.metadata["type"])
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (thought)",
f"{self.metadata['type']} (thought)",
f"New plan:\n{plan_str}",
)
)
@@ -196,7 +196,7 @@ class LedgerOrchestrator(BaseOrchestrator):
ledger_dict = await self.update_ledger()
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (thought)",
f"{self.metadata['type']} (thought)",
f"Updated Ledger:\n{json.dumps(ledger_dict, indent=2)}",
)
)
@@ -204,7 +204,7 @@ class LedgerOrchestrator(BaseOrchestrator):
if ledger_dict["is_request_satisfied"]["answer"] is True:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (thought)",
f"{self.metadata['type']} (thought)",
"Request satisfied.",
)
)
@@ -219,7 +219,7 @@ class LedgerOrchestrator(BaseOrchestrator):
if self._replan_counter < self._max_replans:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (thought)",
f"{self.metadata['type']} (thought)",
"Stalled.... Replanning...",
)
)
@@ -227,7 +227,7 @@ class LedgerOrchestrator(BaseOrchestrator):
else:
logger.info(
OrchestrationEvent(
f"{self.metadata['name']} (thought)",
f"{self.metadata['type']} (thought)",
"Replan counter exceeded... Terminating.",
)
)
@@ -235,11 +235,11 @@ class LedgerOrchestrator(BaseOrchestrator):
next_agent_name = ledger_dict["next_speaker"]["answer"]
for agent in self._agents:
if (await agent.metadata)["name"] == next_agent_name:
if (await agent.metadata)["type"] == next_agent_name:
# broadcast a new message
instruction = ledger_dict["instruction_or_question"]["answer"]
user_message = UserMessage(content=instruction, source=self.metadata["name"])
logger.info(OrchestrationEvent(f"{self.metadata['name']} (-> {next_agent_name})", instruction))
user_message = UserMessage(content=instruction, source=self.metadata["type"])
logger.info(OrchestrationEvent(f"{self.metadata['type']} (-> {next_agent_name})", instruction))
await self.publish_message(BroadcastMessage(content=user_message, request_halt=False))
return agent

View File

@@ -18,7 +18,7 @@ class ReflexAgent(TypeRoutedAgent):
async def handle_request_reply_message(
self, message: RequestReplyMessage, cancellation_token: CancellationToken
) -> None:
name = self.metadata["name"]
name = self.metadata["type"]
response_message = UserMessage(
content=f"Hello, world from {name}!",