camel icon indicating copy to clipboard operation
camel copied to clipboard

[Feature Request] `Message` refactor

Open Wendong-Fan opened this issue 8 months ago • 1 comments

Required prerequisites

  • [X] I have searched the Issue Tracker and Discussions that this hasn't already been reported. (+1 or comment there if it has.)
  • [ ] Consider asking first in a Discussion.

Motivation

learn from standards like FIPA and XMPP, refactor Message to make it more scalable to multi-agent communication

Solution

Requirements on agents:

Agents should send not-understood if they receive a message that they do not recognise or they are unable to process the content of the message. Agents must be prepared to receive and properly handle a not-understood message from other agents.

message attributes:

  • :message-id

    unique id for this message

  • :type

    type of the message

  • :sender

    Denotes the identity of the sender of the message, i.e. the name of the agent of the communicative act.

    {role_name, role_type}

  • :receiver

    Denotes the identity of the intended recipient of the mess age. Note that the recipient may be a single agent name, or a tuple of agent names. This corresponds to the action of multicasting the message. Pragmatically, the semantics of this multicast is that the message is sent to each agent named in the tuple, and that the sender intends each of them to be recipient of the CA encoded in the message. For example, if an agent performs an inform act with a tuple of three agents as receiver, it denotes that the sender intends each of these agent to come to believe the content of the message.

  • :subject

    The subject of this message

  • :content

    Denotes the content of the message; equivalently denotes the object of the action.

    {text, image, audio, video, tool_calling(tools, args, results)}

    msg1 “content”, msg2 “content”

    Multipurpose Internet Mail Extensions (MIME)

  • :reply-with

    Introduces an expression which will be used by the agent responding to this message to identify the original message. Can be used to follow a conversation thread in a situation where multiple dialogues occur simultaneously.

    E.g. if agent i sends to agent j a message which contains

    :reply-with query1, agent j will respond with a message containing

    :in-reply-to query1.

  • :in-reply-to

    [message1,message2] → memory

    Denotes an expression that references an earlier action to which this message is a reply.

  • :envelope

    {time sent:xx, time received:xx}

    Denotes an expression that provides useful information about the message as seen by the message transport service. The content of this parameter is not defined in the specification, but may include time sent, time received, route, etc. The structure of the envelope is a list of keyword value pairs, each of which denotes some aspect of the message service.

  • :language

    Denotes the encoding scheme of the content of the action.

  • :ontology

    Denotes the ontology which is used to give a meaning to the symbols in the content expression.

  • ~~:reply-by~~

    ~~Denotes a time and/or date expression which indicates a guideline on the latest time by which the sending agent would like a reply.~~

  • :protocol

    {schema: Multipurpose Internet Mail Extensions (MIME)}

    Introduces an identifier which denotes the protocol which the sending agent is employing. The protocol serves to give additional context for the interpretation of the message.

  • :conversation-id / thread-id

    uuid

    Introduces an expression which is used to identify an ongoing sequence of communicative acts which together form a conversation. A conversation may be used by an agent to manage its communication strategies and activities. In addition the conversation may provide additional context for the interpretation of the meaning of a message.

message types:

Information passing

  • confirm
  • disconfirm
  • failure inform
  • inform-if (macro act)
  • inform-ref (macro act)

Requesting information

  • query-if (could be Task with attribute description, expected_output, structured output schema, tools specified to use,)
  • query-ref refuse
  • subscribe

Negotiation

  • accept-proposal
  • cfp
  • propose
  • reject-proposal

Action performing

  • agree
  • cancel
  • query-ref refuse
  • request
  • request-when
  • request-whenever

Error handling

  • failure inform
  • not-understood

Structured Output:

output_file: File path for storing messag output.
output_json: Pydantic model for structuring JSON output.
output_pydantic: Pydantic model for task output.

https://github.com/outlines-dev/outlines

https://github.com/jxnl/instructor

https://github.com/argilla-io/distilabel

Message Storage:

SQLLite

MySQL

PostgreSQL https://www.postgresql.org/

PostgreSQL supports complex data types such as JSON and JSONB, which can be useful for storing the structured message content with varied data types (text, image, audio, video, function_calling, etc.). It’s also highly extensible, allowing you to define custom functions, data types, and operators that can be very useful for your specific use case.

Example Schema Design in PostgreSQL:

CREATE TABLE agents (
    agent_id SERIAL PRIMARY KEY,
    role_name VARCHAR(255),
    role_type VARCHAR(255)
);

CREATE TABLE messages (
    message_id UUID PRIMARY KEY,
    sender_id INTEGER REFERENCES agents(agent_id),
    receiver_ids INTEGER[] REFERENCES agents(agent_id),
    content JSONB,
    reply_with UUID[],
    in_reply_to UUID[],
    envelope JSONB,
    language VARCHAR(255),
    ontology VARCHAR(255),
    reply_by TIMESTAMP,
    protocol JSONB,
    conversation_id UUID
);

Draft implementation for Message class:

from dataclasses import dataclass, field
from typing import Any, Dict, List, Tuple, Union
import uuid

@data. class
class Message:
    message_id: str = field(default_factory=lambda: str(uuid.uuid4()))
    type: str
    sender: Tuple[str, str]  # (role_name, role_type)
    receiver: Union[str, Tuple[str, ...]]  # Single agent or tuple of agents
    subject: str
    content: Any  # Could be text, image, audio, video, function_calling
    reply_with: List[str] = field(default_factory=list)
    in_reply_to: List[str] = field(default_factory=list)
    envelope: Dict[str, Any] = field(default_factory=dict)
    language: str
    ontology: str
    reply_by: str  # Time/date expression
    protocol: Dict[str, str] = field(default_factory=lambda: {"schema": "MIME"})
    conversation_id: str = field(default_factory=lambda: str(uuid.uuid4()))
    structured_output: Any = None  # Placeholder for structured output models

Discussion:

also add verbose?

unify current CAMEL message and response into 1?

Alternatives

No response

Additional context

No response

Wendong-Fan avatar Jun 07 '24 14:06 Wendong-Fan