Conversation

Conversation 是一种智能体间交换和共享信息的设计模式,常见于游戏、聊天机器人和多智能体讨论场景。

在 AgentScope 中,conversation 的构建在 显式的消息传递 基础上。在本章中,我们将演示如何构建:

  • User-assistant 之间的对话(聊天机器人)

  • 多实体对话(游戏、讨论等)

它们的主要区别在于

  • 提示的构建方式,以及

  • 信息在智能体之间的 传播/共享 方式。

import asyncio
import json
import os

from agentscope.agent import ReActAgent, UserAgent
from agentscope.memory import InMemoryMemory
from agentscope.formatter import (
    DashScopeChatFormatter,
    DashScopeMultiAgentFormatter,
)
from agentscope.model import DashScopeChatModel
from agentscope.message import Msg
from agentscope.pipeline import MsgHub
from agentscope.tool import Toolkit

User-Assistant 对话

User-assistant 对话,也称为聊天机器人(chatbot),是最常见的智能体应用,也是当前大多数 LLM API 的设计模式。 在这种对话只有两个参与者:用户(user)和智能体(assistant)。

在 AgentScope 中,名称中带有 "Chat" 的格式化器专为 user-assistant 对话设计, 如 DashScopeChatFormatterAnthropicChatFormatter 等。 它们使用消息中的 role 字段来区分用户和智能体,并相应地格式化消息。

这里我们构建智能体 Friday 和用户之间的简单对话。

小技巧

AgentScope 提供了内置的 UserAgent 类,用于人机交互(HITL)。更多详细信息请参考 user-agent

friday = ReActAgent(
    name="Friday",
    sys_prompt="你是一个名为 Friday 的有用助手",
    model=DashScopeChatModel(
        model_name="qwen-max",
        api_key=os.environ["DASHSCOPE_API_KEY"],
    ),
    formatter=DashScopeChatFormatter(),  # 用于 user-assistant 对话的格式化器
    memory=InMemoryMemory(),
    toolkit=Toolkit(),
)

# 创建用户智能体
user = UserAgent(name="User")

现在,我们可以通过在这两个智能体之间交换消息来开始对话,直到用户输入"exit"结束对话。

async def run_conversation() -> None:
    """运行 Friday 和用户之间的简单对话。"""
    msg = None
    while True:
        msg = await friday(msg)
        msg = await user(msg)
        if msg.get_text_content() == "exit":
            break

asyncio.run(run_conversation())

多实体对话

如开头所述,我们演示如何在 提示构建信息共享 方面构建多智能体对话。

构建提示

在 AgentScope 中,我们为多智能体对话提供了内置格式化器,其名称中带有 "MultiAgent", 如 DashScopeMultiAgentFormatterAnthropicMultiAgentFormatter 等。

具体而言,它们使用消息中的 name 字段来区分不同的实体,并将对话历史格式化为单个用户消息。 以 DashScopeMultiAgentFormatter 为例:

小技巧

有关格式化器的更多详细信息可以在 提示词格式化 中找到。

async def example_multi_agent_prompt() -> None:
    msgs = [
        Msg("system", "你是一个名为 Bob 的有用助手。", "system"),
        Msg("Alice", "嗨!", "user"),
        Msg("Bob", "嗨!很高兴见到大家。", "assistant"),
        Msg("Charlie", "我也是!顺便说一下,我是 Charlie。", "assistant"),
    ]

    formatter = DashScopeMultiAgentFormatter()
    prompt = await formatter.format(msgs)

    print("格式化的提示:")
    print(json.dumps(prompt, indent=4, ensure_ascii=False))

    # 我们在这里打印组合用户消息的内容以便更好地理解:
    print("-------------")
    print("组合消息")
    print(prompt[1]["content"])


asyncio.run(example_multi_agent_prompt())
格式化的提示:
[
    {
        "role": "system",
        "content": "你是一个名为 Bob 的有用助手。"
    },
    {
        "role": "user",
        "content": "# Conversation History\nThe content between <history></history> tags contains your conversation history\n<history>\nAlice: 嗨!\nBob: 嗨!很高兴见到大家。\nCharlie: 我也是!顺便说一下,我是 Charlie。\n</history>"
    }
]
-------------
组合消息
# Conversation History
The content between <history></history> tags contains your conversation history
<history>
Alice: 嗨!
Bob: 嗨!很高兴见到大家。
Charlie: 我也是!顺便说一下,我是 Charlie。
</history>

消息共享

在多智能体对话中,显式交换消息可能不够高效和便利, 特别是在多个智能体之间广播消息时。

因此,AgentScope 提供了一个名为 MsgHub 的异步上下文管理器来简化消息广播。 具体而言,同一个 MsgHub 中的智能体将自动接收其它参与者通过 reply 函数返回的消息。

下面我们构建一个多人聊天的场景,多个智能体扮演不同的角色:

model = DashScopeChatModel(
    model_name="qwen-max",
    api_key=os.environ["DASHSCOPE_API_KEY"],
)
formatter = DashScopeMultiAgentFormatter()

alice = ReActAgent(
    name="Alice",
    sys_prompt="你是一个名为 Alice 的学生。",
    model=model,
    formatter=formatter,
)

bob = ReActAgent(
    name="Bob",
    sys_prompt="你是一个名为 Bob 的学生。",
    model=model,
    formatter=formatter,
)

charlie = ReActAgent(
    name="Charlie",
    sys_prompt="你是一个名为 Charlie 的学生。",
    model=model,
    formatter=formatter,
)


async def example_msghub() -> None:
    """使用 MsgHub 进行多智能体对话的示例。"""
    async with MsgHub(
        [alice, bob, charlie],
        # 进入 MsgHub 时的公告消息
        announcement=Msg(
            "system",
            "现在大家互相认识一下,简单自我介绍。",
            "system",
        ),
    ):
        await alice()
        await bob()
        await charlie()


asyncio.run(example_msghub())
Alice: 大家好,我叫Alice,是一名学生。很高兴认识大家!我喜欢阅读和探索新知识,也热衷于参加各种户外活动。希望我们能成为好朋友,一起分享学习和生活中的点滴。你们都有什么兴趣爱好呢?
Bob: 大家好,我叫Bob,也是学生。我对科学和技术特别感兴趣,平时喜欢捣鼓一些电子设备,也爱玩视频游戏。我也很期待和大家成为朋友,一起学习进步。很高兴遇到有共同话题的朋友!Alice,你最喜欢哪类书籍?
Charlie: 大家好,我叫Charlie,和你们一样也是学生。我对音乐特别有热情,平时喜欢弹吉他和写歌。我也热爱体育,特别是篮球。在学习上,我对数学和物理很感兴趣。Alice,你最喜欢哪种类型的户外活动?Bob,你最近在玩什么视频游戏?希望我们能一起分享我们的兴趣!

现在我们打印 Alice 的记忆,检查她的记忆是否正确更新。

async def example_memory() -> None:
    """打印 Alice 的记忆。"""
    print("Alice 的记忆:")
    for msg in await alice.memory.get_memory():
        print(
            f"{msg.name}: {json.dumps(msg.content, indent=4, ensure_ascii=False)}",
        )


asyncio.run(example_memory())
Alice 的记忆:
system: "现在大家互相认识一下,简单自我介绍。"
Alice: [
    {
        "id": "WRC9oxPwwWJvsQK5aeJ9YW",
        "type": "tool_use",
        "name": "generate_response",
        "input": {
            "response": "大家好,我叫Alice,是一名学生。很高兴认识大家!我喜欢阅读和探索新知识,也热衷于参加各种户外活动。希望我们能成为好朋友,一起分享学习和生活中的点滴。你们都有什么兴趣爱好呢?"
        }
    }
]
system: [
    {
        "type": "tool_result",
        "id": "WRC9oxPwwWJvsQK5aeJ9YW",
        "name": "generate_response",
        "output": [
            {
                "type": "text",
                "text": "Successfully generated response."
            }
        ]
    }
]
Alice: "大家好,我叫Alice,是一名学生。很高兴认识大家!我喜欢阅读和探索新知识,也热衷于参加各种户外活动。希望我们能成为好朋友,一起分享学习和生活中的点滴。你们都有什么兴趣爱好呢?"
Bob: "大家好,我叫Bob,也是学生。我对科学和技术特别感兴趣,平时喜欢捣鼓一些电子设备,也爱玩视频游戏。我也很期待和大家成为朋友,一起学习进步。很高兴遇到有共同话题的朋友!Alice,你最喜欢哪类书籍?"
Charlie: "大家好,我叫Charlie,和你们一样也是学生。我对音乐特别有热情,平时喜欢弹吉他和写歌。我也热爱体育,特别是篮球。在学习上,我对数学和物理很感兴趣。Alice,你最喜欢哪种类型的户外活动?Bob,你最近在玩什么视频游戏?希望我们能一起分享我们的兴趣!"

进一步阅读

Total running time of the script: (0 minutes 16.068 seconds)

Gallery generated by Sphinx-Gallery