diff --git a/docs/sphinx_doc/source/tutorial/205-memory.md b/docs/sphinx_doc/source/tutorial/205-memory.md index 728bc1f29..a03d67652 100644 --- a/docs/sphinx_doc/source/tutorial/205-memory.md +++ b/docs/sphinx_doc/source/tutorial/205-memory.md @@ -1,17 +1,48 @@ (205-memory)= -# Memory and Message Management +# About Memory + +In AgentScope, memory is used to store historical information, allowing the +agent to provide more coherent and natural responses based on context. +This tutorial will first introduce the carrier of information in memory, +message, and then introduce the functions and usage of the memory module in +AgentScope. + +## About Message + +### `MessageBase` Class + +In AgentScope, the message base class is a subclass of Python dictionary, +consisting of two required fields (`name` and `content`) and an optional +field (`url`). +Specifically, the `name` field represents the originator of the message, +the `content` field represents the content of the message, and the `url` +field represents the data link attached to the message, which can be a +local link to multi-modal data or a web link. +As a dictionary type, developers can also add other fields +as needed. When a message is created, a unique ID is automatically +generated to identify the message. The creation time of the message is also +automatically recorded in the form of a timestamp. + +In the specific implementation, AgentScope first provides a `MessageBase` +base class to define the basic properties and usage of messages. +Unlike general dictionary types, the instantiated objects of `MessageBase` +can access attribute values through `object_name.{attribute_name}` or +`object_name['attribute_name']`. +The key attributes of the `MessageBase` class are as follows: -**Message** represents individual pieces of information or interactions flowing between/within agents. **Memory** refers to the storage and retrieval of historical information and serves as the storage and management system for the messages. This allows the agent to remember past interactions, maintain context, and provide more coherent and relevant responses. - -## Understanding `MessageBase` and its subclasses - -### `MessageBase` - -`MessageBase` is designed to organize attributes of a message, like the agent's name, the content, and associated media URLs. It provides a structure that can be extended to create specific types of messages. +- **`name`**: This attribute denotes the originator of the message. It's a critical piece of metadata, useful in scenarios where distinguishing between different speakers is necessary. +- **`content`**: The substance of the message itself. It can include text, structured data, or any other form of content that is relevant to the interaction and requires processing by the agent. +- **`url`**: An optional attribute that allows the message to be linked to external resources. These can be direct links to files, multi-modal data, or web pages. +- **`timestamp`**: A timestamp indicating when the message was created. +- **`id`**: Each message is assigned a unique identifier (ID) upon creation. ```python class MessageBase(dict): + """Base Message class, which is used to maintain information for dialog, + memory and used to construct prompt. + """ + def __init__( self, name: str, @@ -20,68 +51,114 @@ class MessageBase(dict): timestamp: Optional[str] = None, **kwargs: Any, ) -> None: + """Initialize the message object + + Args: + name (`str`): + The name of who send the message. It's often used in + role-playing scenario to tell the name of the sender. + However, you can also only use `role` when calling openai api. + The usage of `name` refers to + https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models. + content (`Any`): + The content of the message. + url (`Optional[Union[list[str], str]]`, defaults to None): + A url to file, image, video, audio or website. + timestamp (`Optional[str]`, defaults to None): + The timestamp of the message, if None, it will be set to + current time. + **kwargs (`Any`): + Other attributes of the message. For OpenAI API, you should + add "role" from `["system", "user", "assistant", "function"]`. + When calling OpenAI API, `"role": "assistant"` will be added + to the messages that don't have "role" attribute. + + """ + # id and timestamp will be added to the object as its attributes + # rather than items in dict self.id = uuid4().hex - self.timestamp = timestamp or _get_timestamp() + if timestamp is None: + self.timestamp = _get_timestamp() + else: + self.timestamp = timestamp + self.name = name self.content = content - self.url = url + + if url: + self.url = url + self.update(kwargs) + def __getattr__(self, key: Any) -> Any: + try: + return self[key] + except KeyError as e: + raise AttributeError(f"no attribute '{key}'") from e + + def __setattr__(self, key: Any, value: Any) -> None: + self[key] = value + + def __delattr__(self, key: Any) -> None: + try: + del self[key] + except KeyError as e: + raise AttributeError(f"no attribute '{key}'") from e + def to_str(self) -> str: + """Return the string representation of the message""" raise NotImplementedError def serialize(self) -> str: + """Return the serialized message.""" raise NotImplementedError - # ... [code omitted for brevity] + # ... [省略代码以简化] ``` -Here are the key attributes managed by the `MessageBase` class: - -- **`name`**: This attribute denotes the originator of the message. It's a critical piece of metadata, useful in scenarios where distinguishing between different speakers is necessary. -- **`content`**: The substance of the message itself. It can include text, structured data, or any other form of content that is relevant to the interaction and requires processing by the agent. -- **`url`**: An optional attribute that allows the message to be linked to external resources. These can be direct links to files, multi-modal data, or web pages. -- **`timestamp`**: A timestamp indicating when the message was created. -- **`id`**: Each message is assigned a unique identifier (ID) upon creation. - -### `Msg` +### `Msg` Class -The `Msg` ("Message") subclass extends `MessageBase` and represents a standard *message*. `Msg` provides concrete definitions for the `to_str` and `serialize` methods to enable string representation and serialization suitable for the agent's operational context. +`Msg` class extends `MessageBase` and represents a standard *message*. +`Msg` provides concrete definitions for the `to_str` and `serialize` +methods to enable string representation and serialization suitable for the +agent's operational context. +Within an `Agent` class, its `reply` function typically returns an instance of +`Msg` to facilitate message passing within AgentScope. ```python class Msg(MessageBase): - # ... [code omitted for brevity] + """The Message class.""" + + def __init__( + self, + name: str, + content: Any, + url: Optional[Union[Sequence[str], str]] = None, + timestamp: Optional[str] = None, + echo: bool = False, + **kwargs: Any, + ) -> None: + super().__init__( + name=name, + content=content, + url=url, + timestamp=timestamp, + **kwargs, + ) + if echo: + logger.chat(self) def to_str(self) -> str: + """Return the string representation of the message""" return f"{self.name}: {self.content}" def serialize(self) -> str: return json.dumps({"__type": "Msg", **self}) - -# `Msg` logs ->> Someone: I should ... -``` - -### `Tht` - -The `Tht` ("Thought") subclass is a specialized form of `MessageBase` used for encapsulating processes of an agent's internal thought. The thought is not sent outwardly but is instead used internally by the agent. As with `Msg`, specific implementations of `Tht` will define `to_str` and `serialize` methods to handle the unique requirements of representing and serializing an agent's thoughts. - -```python -class Tht(MessageBase): - # ... [code omitted for brevity] - - def to_str(self) -> str: - return f"{self.name} thought: {self.content}" - - def serialize(self) -> str: - return json.dumps({"__type": "Tht", **self}) - ->> Someone thought: I should ... ``` -## Understanding `MemoryBase` and its subclasses +## About Memory -### `MemoryBase` +### `MemoryBase` Class `MemoryBase` is an abstract class that handles an agent's memory in a structured way. It defines operations for storing, retrieving, deleting, and manipulating *message*'s content. @@ -143,4 +220,4 @@ The `TemporaryMemory` class is a concrete implementation of `MemoryBase`, provid For more details about the usage of `Memory` and `Msg`, please refer to the API references. -[[Return to the top]](#memory-and-message-management) +[[Return to the top]](#about-memory) diff --git a/docs/sphinx_doc/source/tutorial/206-prompt.md b/docs/sphinx_doc/source/tutorial/206-prompt.md index de580de47..49adffa2c 100644 --- a/docs/sphinx_doc/source/tutorial/206-prompt.md +++ b/docs/sphinx_doc/source/tutorial/206-prompt.md @@ -2,16 +2,23 @@ # Prompt Engine -**Prompt** is a crucial component in interacting with language models, especially when seeking to generate specific types of outputs or guide the model toward desired behaviors. This tutorial will guide you through the use of the `PromptEngine` class, which simplifies the process of crafting prompts for LLMs. - -## Understanding the `PromptEngine` Class +**Prompt** is a crucial component in interacting with language models, +especially when seeking to generate specific types of outputs or guide the +model toward desired behaviors. +AgentScope allows developers to customize prompts according to their needs, +and provides the `PromptEngine` class to simplify the process of crafting +prompts for large language models (LLMs). +This tutorial will guide you through the +use of the `PromptEngine` class, which simplifies the process of crafting +prompts for LLMs. + +## About `PromptEngine` Class The `PromptEngine` class provides a structured way to combine different components of a prompt, such as instructions, hints, dialogue history, and user inputs, into a format that is suitable for the underlying language model. ### Key Features of PromptEngine - **Model Compatibility**: It works with any `ModelWrapperBase` subclass. -- **Shrink Policy**: It offers two policies for handling prompts that exceed the maximum length: `ShrinkPolicy.TRUNCATE` to simply truncate the prompt, and `ShrinkPolicy.SUMMARIZE` to summarize part of the dialog history to save space. - **Prompt Type**: It supports both string and list-style prompts, aligning with the model's preferred input format. ### Initialization diff --git a/docs/sphinx_doc/source/tutorial/zh/103-example.md b/docs/sphinx_doc/source/tutorial/zh/103-example.md index 75dc883ce..5f9e216b9 100644 --- a/docs/sphinx_doc/source/tutorial/zh/103-example.md +++ b/docs/sphinx_doc/source/tutorial/zh/103-example.md @@ -37,7 +37,7 @@ model_config = { ``` 对于开源模型,我们支持与HuggingFace、ModelScope、FastChat和vllm等各种模型接口的集成。您可以在`scripts -`目录中找到部署这些服务的脚本,详细说明请见[[Using Different Model Sources with Model API]](203-model). +`目录中找到部署这些服务的脚本,详细说明请见[[模型服务]](203-model). 您可以通过调用AgentScope的初始化方法来注册您的配置。此外,您还可以一次性加载多个模型配置。 @@ -45,8 +45,12 @@ model_config = { import agentscope # 一次性初始化多个模型配置 -openai_cfg_dict = {...dict_filling...} -modelscope_cfg_dict = {...dict_filling...} +openai_cfg_dict = { + # ... +} +modelscope_cfg_dict = { + # ... +} agentscope.init(model_configs=[openai_cfg_dict, modelscope_cfg_dict]) ``` diff --git a/docs/sphinx_doc/source/tutorial/zh/205-memory.md b/docs/sphinx_doc/source/tutorial/zh/205-memory.md index ea75271c9..dbe9ceacd 100644 --- a/docs/sphinx_doc/source/tutorial/zh/205-memory.md +++ b/docs/sphinx_doc/source/tutorial/zh/205-memory.md @@ -1,17 +1,41 @@ (205-memory)= -# 信息和记忆管理 +# 关于记忆 -**信息(message)**代表智能体之间或智能体内部传递的单个信息片段或交互。**记忆(memory)**指历史信息的存储和检索,是信息的存储和管理系统。这使智能体能够记住过去的互动信息,保持上下文关联,以提供更连贯、更相关的响应。 +AgentScope中,记忆(memory)用于存储历史消息,从而使智能体能够根据上下文提供更加连贯,更加 +自然的响应。 +本教程将首先介绍memory中信息的载体,消息(message),然后介绍AgentScope中记忆模块的功能 +和使用方法。 -## 理解 `MessageBase` 及其子类 +## 关于消息(Message) -### `MessageBase` -`MessageBase` 旨在组织信息的属性,如智能体名字、内容和相关媒体 URL,它提供了一种可扩展的结构,用于创建特定类型的信息。 +### 消息基类(`MessageBase`) + +AgentScope中,消息基类是Python字典的子类,由`name`,`content`两个必选字段和一个可选的字段 +`url`组成。由于是字典类型,开发者也可以根据需要增加其他字段。 +其中,`name`字段代表消息的发起者,`content`字段代表消息的内容,`url +`则代表消息中附加的数据链接,可以是指向多模态数据的本地链接,也可以是网络链接。 +当一个消息被创建时,将会自动创建一个唯一的ID,用于标识这条消息。同时,消息的创建时间也会以 +时间戳的形式自动记录下来。 + +具体实现中,AgentScope首先提供了一个`MessageBase`基类,用于定义消息的基本属性和使用方法。 +与一般的字典类型不同,`MessageBase`的实例化对象可以通过`对象名.{属性名}`的方式访问属性值, +也可以通过`对象名['属性名']`的方式访问属性值。 +其中,`MessageBase` 类的关键属性如下: + +- **`name`**:该属性表示信息的发起者。这是一项关键的元数据,在需要区分不同发言者的场景中非常有用。 +- **`content`**:信息本身的内容。它可以包括文本、结构化数据或其他与交互相关且需要智能体处理的内容形式。 +- **`url`**:可选属性,允许信息链接到外部资源。这些可以是指向文件的直接链接、多模态数据或网页。 +- **`timestamp`**:时间戳,显示信息创建的时间。 +- **`id`**:每条信息在创建时都会被分配一个唯一标识符(ID)。 ```python class MessageBase(dict): + """Base Message class, which is used to maintain information for dialog, + memory and used to construct prompt. + """ + def __init__( self, name: str, @@ -20,70 +44,115 @@ class MessageBase(dict): timestamp: Optional[str] = None, **kwargs: Any, ) -> None: + """Initialize the message object + + Args: + name (`str`): + The name of who send the message. It's often used in + role-playing scenario to tell the name of the sender. + However, you can also only use `role` when calling openai api. + The usage of `name` refers to + https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models. + content (`Any`): + The content of the message. + url (`Optional[Union[list[str], str]]`, defaults to None): + A url to file, image, video, audio or website. + timestamp (`Optional[str]`, defaults to None): + The timestamp of the message, if None, it will be set to + current time. + **kwargs (`Any`): + Other attributes of the message. For OpenAI API, you should + add "role" from `["system", "user", "assistant", "function"]`. + When calling OpenAI API, `"role": "assistant"` will be added + to the messages that don't have "role" attribute. + + """ + # id and timestamp will be added to the object as its attributes + # rather than items in dict self.id = uuid4().hex - self.timestamp = timestamp or _get_timestamp() + if timestamp is None: + self.timestamp = _get_timestamp() + else: + self.timestamp = timestamp + self.name = name self.content = content - self.url = url + + if url: + self.url = url + self.update(kwargs) + def __getattr__(self, key: Any) -> Any: + try: + return self[key] + except KeyError as e: + raise AttributeError(f"no attribute '{key}'") from e + + def __setattr__(self, key: Any, value: Any) -> None: + self[key] = value + + def __delattr__(self, key: Any) -> None: + try: + del self[key] + except KeyError as e: + raise AttributeError(f"no attribute '{key}'") from e + def to_str(self) -> str: + """Return the string representation of the message""" raise NotImplementedError def serialize(self) -> str: + """Return the serialized message.""" raise NotImplementedError # ... [省略代码以简化] ``` - `MessageBase` 类的关键属性如下: - -- **`name`**:该属性表示信息的发起者。这是一项关键的元数据,在需要区分不同发言者的场景中非常有用。 -- **`content`**:信息本身的内容。它可以包括文本、结构化数据或其他与交互相关且需要智能体处理的内容形式。 -- **`url`**:可选属性,允许信息链接到外部资源。这些可以是指向文件的直接链接、多模态数据或网页。 -- **`timestamp`**:时间戳,显示信息创建的时间。 -- **`id`**:每条信息在创建时都会被分配一个唯一标识符(ID)。 - -### `Msg` +### 消息类(`Msg`) - `Msg` ("Message")子类扩展了 `MessageBase` ,代表了一个标准的*信息*。`Msg` 提供了对 `to_str` 和 `serialize` 方法的具体定义,以便于字符串表示和序列化,适合智能体对上下文的操作。 +`Msg`类是AgentScope中最常用的消息类。它继承了 `MessageBase`类,并实现了`to_str` 和 +`serialize` 抽象方法。 +在一个Agent类中,其`reply`函数通常会返回一个`Msg`类的实例,以便在AgentScope中进行消息的 +传递。 ```python class Msg(MessageBase): - # ... [省略代码以简化] + """The Message class.""" + + def __init__( + self, + name: str, + content: Any, + url: Optional[Union[Sequence[str], str]] = None, + timestamp: Optional[str] = None, + echo: bool = False, + **kwargs: Any, + ) -> None: + super().__init__( + name=name, + content=content, + url=url, + timestamp=timestamp, + **kwargs, + ) + if echo: + logger.chat(self) def to_str(self) -> str: + """Return the string representation of the message""" return f"{self.name}: {self.content}" def serialize(self) -> str: return json.dumps({"__type": "Msg", **self}) - -# `Msg` 日志 ->> Someone: I should ... -``` - -### `Tht` - -`Tht`("Thought")子类是 `MessageBase` 的一种特殊形式,用于封装智能体内部思考的过程。思考不向外发送,而是智能体内部使用。与 `Msg` 一样,特定的 `Tht` 实现将定义 `to_str` 和 `serialize` 方法,来处理对智能体思考内容的字符串表示和序列化的独特需求。 - -```python -class Tht(MessageBase): - # ... [省略代码以简化] - - def to_str(self) -> str: - return f"{self.name} thought: {self.content}" - - def serialize(self) -> str: - return json.dumps({"__type": "Tht", **self}) - ->> Someone thought: I should ... ``` -## 理解 `MemoryBase` 及其子类 +## 关于记忆(Memory) -### `MemoryBase` +### 关于记忆基类(`MemoryBase`) -`MemoryBase` 是一个抽象类,以结构化的方式处理智能体的记忆。它定义了存储、检索、删除和操作*信息*内容的操作。 +`MemoryBase` 是一个抽象类,以结构化的方式处理智能体的记忆。它定义了存储、检索、删除和操作 +*信息*内容的操作。 ```python class MemoryBase(ABC): @@ -134,7 +203,7 @@ class MemoryBase(ABC): - **`clear`**:这个方法清除智能体记忆中的所有*信息*,本质上是重置。 - **`size`**:这个方法返回当前存储在智能体记忆中的信息数量。 -### `TemporaryMemory` +### 关于`TemporaryMemory` `TemporaryMemory ` 类是 `MemoryBase` 类的一个具体实现,提供了一个智能体运行期间存在的记忆存储,被用作智能体的默认记忆类型。除了 `MemoryBase` 的所有行为外,`TemporaryMemory ` 还提供了检索的方法: @@ -143,4 +212,4 @@ class MemoryBase(ABC): 有关 `Memory` 和 `Msg` 使用的更多细节,请参考 API 文档。 -[[返回顶端]](#信息和记忆管理) +[[返回顶端]](#关于记忆) diff --git a/docs/sphinx_doc/source/tutorial/zh/206-prompt.md b/docs/sphinx_doc/source/tutorial/zh/206-prompt.md index abd9ead82..071c126cf 100644 --- a/docs/sphinx_doc/source/tutorial/zh/206-prompt.md +++ b/docs/sphinx_doc/source/tutorial/zh/206-prompt.md @@ -2,16 +2,19 @@ # 提示工程 -**提示(prompt)**是与语言模型互动时的关键组件,尤其是当寻求生成特定类型的输出或指导模型朝向期望行为时。本教程将指导您如何使用 `PromptEngine` 类,它简化了为大语言模型(LLMs)制作提示的过程。 +**提示(prompt)**是与语言模型互动时的关键组件,尤其是当寻求生成特定类型的输出或指导模型朝 +向期望行为时。 +AgentScope中允许开发者按照自己的需求定制提示,同时提供了`PromptEngine`类用以简化为大语言 +模型(LLMs)制作提示的过程。 +本教程将主要介绍如何使用`PromptEngine`类构建大模型的提示。 -## 理解 `PromptEngine` 类 +## 关于`PromptEngine`类 -`PromptEngine `类提供了一种结构化的方式来合并不同的提示组件,比如指令、提示、对话历史和用户输入,以适合底层语言模型的格式。 +`PromptEngine`类提供了一种结构化的方式来合并不同的提示组件,比如指令、提示、对话历史和用户输入,以适合底层语言模型的格式。 ### 提示工程的关键特性 - **模型兼容性**:可以与任何 `ModelWrapperBase` 的子类一起工作。 -- **缩减原则**:提供了两种处理超出最大长度提示的方案:`ShrinkPolicy.TRUNCATE` 简单地截断提示,以及 `ShrinkPolicy.SUMMARIZE `总结部分对话历史以节省空间。 - **提示类型**:支持字符串和列表风格的提示,与模型首选的输入格式保持一致。 ### 初始化