camel-ai / camel-ai/camel

[Feature Request] `Message` refactor

Open
#613 1 comment 0 reactions 2 assignees Claimed by @willshang76 View on GitHub
enhancement New Feature P0
Dominant language
Python
Stars
17.7k
Forks
2.1k
Avg merge
5m
Merged PRs (30d)
3

Description

### Required prerequisites

- [X] I have searched the [Issue Tracker](https://github.com/camel-ai/camel/issues) and [Discussions](https://github.com/camel-ai/camel/discussions) that this hasn't already been reported. (+1 or comment there if it has.)
- [ ] Consider asking first in a [Discussion](https://github.com/camel-ai/camel/discussions/new).

### 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:**

```jsx
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:**

```sql
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:**

```python
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_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.