AutoGen实现多代理-Tool_Use_and_Conversational_Chess(四)

1. 学习背景 在这里插入图片描述

如图,常见的Agent之间交流对话,可能会涉及到外部工具的调用和嵌套式聊天,这种设计模式就要求代理会使用工具和按序执行代码。本节尝试聊天机器人模拟人类进行下棋,如图所示,Chess Board代理则进行检测合法性并记录移动。
在这里插入图片描述

2. 代码实践

本节实验链接:传送门

2.1 准备环境

llm_config = {"model": "gpt-4-turbo"}

# 导入与棋盘相关的包
import chess
import chess.svg
from typing_extensions import Annotated

# 初始化棋盘
board = chess.Board()
made_move = False

2.2 定义所需的工具

2.2.1 获取合法移动的工具

def get_legal_moves(
    
) -> Annotated[str, "A list of legal moves in UCI format"]:
    return "Possible moves are: " + ",".join(
        [str(move) for move in board.legal_moves]
    )

2.2.2 在棋盘上进行移动的工具

def make_move(
    move: Annotated[str, "A move in UCI format."]
) -> Annotated[str, "Result of the move."]:
    move = chess.Move.from_uci(move)
    board.push_uci(str(move))
    global made_move
    made_move = True
    
    # Display the board.
    display(
        chess.svg.board(
            board,
            arrows=[(move.from_square, move.to_square)],
            fill={move.from_square: "gray"},
            size=200
        )
    )
    
    # Get the piece name.
    piece = board.piece_at(move.to_square)
    piece_symbol = piece.unicode_symbol()
    piece_name = (
        chess.piece_name(piece.piece_type).capitalize()
        if piece_symbol.isupper()
        else chess.piece_name(piece.piece_type)
    )
    return f"Moved {piece_name} ({piece_symbol}) from "\
    f"{chess.SQUARE_NAMES[move.from_square]} to "\
    f"{chess.SQUARE_NAMES[move.to_square]}."

2.3 创建代理

你将为棋盘创建玩家代理和棋盘代理。

from autogen import ConversableAgent
# Player white agent
player_white = ConversableAgent(
    name="Player White",
    system_message="You are a chess player and you play as white. "
    "First call get_legal_moves(), to get a list of legal moves. "
    "Then call make_move(move) to make a move.",
    llm_config=llm_config,
)
# Player black agent
player_black = ConversableAgent(
    name="Player Black",
    system_message="You are a chess player and you play as black. "
    "First call get_legal_moves(), to get a list of legal moves. "
    "Then call make_move(move) to make a move.",
    llm_config=llm_config,
)
def check_made_move(msg):
    global made_move
    if made_move:
        made_move = False
        return True
    else:
        return False
board_proxy = ConversableAgent(
    name="Board Proxy",
    llm_config=False,
    is_termination_msg=check_made_move,
    default_auto_reply="Please make a move.",
    human_input_mode="NEVER",
)

2.4 为代理注册可用的工具

调用工具的代理和执行工具的代理都必须为其注册一个工具。

from autogen import register_function
# 为每个代理都注册合法性检测工具和移动工具,方便代理调用
for caller in [player_white, player_black]:
    register_function(
        get_legal_moves,
        caller=caller,
        executor=board_proxy,
        name="get_legal_moves",
        description="Get legal moves.",
    )
    
    register_function(
        make_move,
        caller=caller,
        executor=board_proxy,
        name="make_move",
        description="Call this tool to make a move.",
    )

可以查看代理绑定工具的情况

player_black.llm_config["tools"]

输出如下:

[{'type': 'function',
  'function': {'description': 'Get legal moves.',
   'name': 'get_legal_moves',
   'parameters': {'type': 'object', 'properties': {}, 'required': []}}},
 {'type': 'function',
  'function': {'description': 'Call this tool to make a move.',
   'name': 'make_move',
   'parameters': {'type': 'object',
    'properties': {'move': {'type': 'string',
      'description': 'A move in UCI format.'}},
    'required': ['move']}}}]

2.5 注册嵌套式聊天模式

每个玩家代理将与棋盘代理进行嵌套式聊天,以便在棋盘上进行移动。

player_white.register_nested_chats(
    trigger=player_black,
    chat_queue=[
        {
            "sender": board_proxy,
            "recipient": player_white,
            "summary_method": "last_msg",
        }
    ],
)

player_black.register_nested_chats(
    trigger=player_white,
    chat_queue=[
        {
            "sender": board_proxy,
            "recipient": player_black,
            "summary_method": "last_msg",
        }
    ],
)

2.6 开始游戏

board = chess.Board()

chat_result = player_black.initiate_chat(
    player_white,
    message="Let's play chess! Your move.",
    max_turns=2,
)

输出如下:

Player Black (to Player White):

Let's play chess! Your move.

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...

********************************************************************************
Starting a new chat....

********************************************************************************
Board Proxy (to Player White):

Let's play chess! Your move.

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

***** Suggested tool call (call_Xp271IKAeUo1TxQvoHZ4dWae): get_legal_moves *****
Arguments: 
{}
********************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION get_legal_moves...
Board Proxy (to Player White):

Board Proxy (to Player White):

***** Response from calling tool (call_Xp271IKAeUo1TxQvoHZ4dWae) *****
Possible moves are: g1h3,g1f3,b1c3,b1a3,h2h3,g2g3,f2f3,e2e3,d2d3,c2c3,b2b3,a2a3,h2h4,g2g4,f2f4,e2e4,d2d4,c2c4,b2b4,a2a4
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

***** Suggested tool call (call_XanM9YQcrNYeqGH23xy5Mphx): make_move *****
Arguments: 
{"move":"e2e4"}
**************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION make_move...
Board Proxy (to Player White):

Board Proxy (to Player White):

***** Response from calling tool (call_XanM9YQcrNYeqGH23xy5Mphx) *****
Moved pawn (♙) from e2 to e4.
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

I've moved my pawn from e2 to e4. Your turn!

--------------------------------------------------------------------------------
Player White (to Player Black):

I've moved my pawn from e2 to e4. Your turn!

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...

********************************************************************************
Starting a new chat....

********************************************************************************
Board Proxy (to Player Black):

I've moved my pawn from e2 to e4. Your turn!

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player Black (to Board Proxy):

***** Suggested tool call (call_iNPpTbzXbXjXvkrBir5eMoXg): get_legal_moves *****
Arguments: 
{}
********************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION get_legal_moves...
Board Proxy (to Player Black):

Board Proxy (to Player Black):

***** Response from calling tool (call_iNPpTbzXbXjXvkrBir5eMoXg) *****
Possible moves are: g8h6,g8f6,b8c6,b8a6,h7h6,g7g6,f7f6,e7e6,d7d6,c7c6,b7b6,a7a6,h7h5,g7g5,f7f5,e7e5,d7d5,c7c5,b7b5,a7a5
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player Black (to Board Proxy):

I'll move my pawn from e7 to e5.

Let's execute that move.
***** Suggested tool call (call_OeCdklYTQCRCf3zbDTN4Iyhh): make_move *****
Arguments: 
{"move":"e7e5"}
**************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION make_move...
Board Proxy (to Player Black):

Board Proxy (to Player Black):

***** Response from calling tool (call_OeCdklYTQCRCf3zbDTN4Iyhh) *****
Moved pawn (♟) from e7 to e5.
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player Black (to Board Proxy):

I moved my pawn from e7 to e5. It's your turn!

--------------------------------------------------------------------------------
Player Black (to Player White):

I moved my pawn from e7 to e5. It's your turn!

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...

********************************************************************************
Starting a new chat....

********************************************************************************
Board Proxy (to Player White):

I moved my pawn from e7 to e5. It's your turn!

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

***** Suggested tool call (call_OIZtgdPww7usovnyFNVQuaf2): get_legal_moves *****
Arguments: 
{}
********************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION get_legal_moves...
Board Proxy (to Player White):

Board Proxy (to Player White):

***** Response from calling tool (call_OIZtgdPww7usovnyFNVQuaf2) *****
Possible moves are: g1h3,g1f3,g1e2,f1a6,f1b5,f1c4,f1d3,f1e2,e1e2,d1h5,d1g4,d1f3,d1e2,b1c3,b1a3,h2h3,g2g3,f2f3,d2d3,c2c3,b2b3,a2a3,h2h4,g2g4,f2f4,d2d4,c2c4,b2b4,a2a4
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

***** Suggested tool call (call_o8palhCreQqCGalX2GDOezvj): make_move *****
Arguments: 
{"move":"e2e4"}
**************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION make_move...
Board Proxy (to Player White):

Board Proxy (to Player White):

***** Response from calling tool (call_o8palhCreQqCGalX2GDOezvj) *****
Error: illegal uci: 'e2e4' in rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

It seems there was a misunderstanding; your move, pawn from e7 to e5, has already been reflected on the board. I'll proceed with my move now. Let me make another valid move.
***** Suggested tool call (call_IOkzRwgZ2V61IJeprXUGSbyk): make_move *****
Arguments: 
{"move":"g1f3"}
**************************************************************************

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING FUNCTION make_move...
Board Proxy (to Player White):

Board Proxy (to Player White):

***** Response from calling tool (call_IOkzRwgZ2V61IJeprXUGSbyk) *****
Moved knight (♘) from g1 to f3.
**********************************************************************

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...
Player White (to Board Proxy):

I've moved my knight from g1 to f3. It's your turn!

--------------------------------------------------------------------------------
Player White (to Player Black):

I've moved my knight from g1 to f3. It's your turn!

--------------------------------------------------------------------------------

jupyternotebook执行过程有图,因博客原因,图片复制不出来,见谅。

2.7 为游戏添加有趣的闲聊!

player_white = ConversableAgent(
    name="Player White",
    system_message="You are a chess player and you play as white. "
    "First call get_legal_moves(), to get a list of legal moves. "
    "Then call make_move(move) to make a move. "
    "After a move is made, chitchat to make the game fun.",
    llm_config=llm_config,
)
player_black = ConversableAgent(
    name="Player Black",
    system_message="You are a chess player and you play as black. "
    "First call get_legal_moves(), to get a list of legal moves. "
    "Then call make_move(move) to make a move. "
    "After a move is made, chitchat to make the game fun.",
    llm_config=llm_config,
)
for caller in [player_white, player_black]:
    register_function(
        get_legal_moves,
        caller=caller,
        executor=board_proxy,
        name="get_legal_moves",
        description="Get legal moves.",
    )

    register_function(
        make_move,
        caller=caller,
        executor=board_proxy,
        name="make_move",
        description="Call this tool to make a move.",
    )

player_white.register_nested_chats(
    trigger=player_black,
    chat_queue=[
        {
            "sender": board_proxy,
            "recipient": player_white,
            "summary_method": "last_msg",
            "silent": True,
        }
    ],
)

player_black.register_nested_chats(
    trigger=player_white,
    chat_queue=[
        {
            "sender": board_proxy,
            "recipient": player_black,
            "summary_method": "last_msg",
            "silent": True,
        }
    ],
)
board = chess.Board()

chat_result = player_black.initiate_chat(
    player_white,
    message="Let's play chess! Your move.",
    max_turns=2,
)

输出如下:

Player Black (to Player White):

Let's play chess! Your move.

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...

********************************************************************************
Starting a new chat....

********************************************************************************

>>>>>>>> USING AUTO REPLY...

>>>>>>>> EXECUTING FUNCTION get_legal_moves...

>>>>>>>> USING AUTO REPLY...

>>>>>>>> EXECUTING FUNCTION make_move...

>>>>>>>> USING AUTO REPLY...
Player White (to Player Black):

Great! I've moved my pawn to e4. It's your turn now. How do you like to open your games when you play chess? Do you prefer more aggressive openings or a solid, defensive setup?

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...

********************************************************************************
Starting a new chat....

********************************************************************************

>>>>>>>> USING AUTO REPLY...

>>>>>>>> EXECUTING FUNCTION get_legal_moves...

>>>>>>>> USING AUTO REPLY...

>>>>>>>> EXECUTING FUNCTION make_move...

>>>>>>>> USING AUTO REPLY...
Player Black (to Player White):

The pawn has moved to e5, and now I'm looking forward to seeing your next strategy. It seems like we are gearing up for a classical open game!

Tell me about your chess experiences. Have you had any memorable games or achievements that stand out in your journey as a chess player?

--------------------------------------------------------------------------------

>>>>>>>> USING AUTO REPLY...

********************************************************************************
Starting a new chat....

********************************************************************************

>>>>>>>> USING AUTO REPLY...

>>>>>>>> EXECUTING FUNCTION get_legal_moves...

>>>>>>>> USING AUTO REPLY...

>>>>>>>> USING AUTO REPLY...

>>>>>>>> EXECUTING FUNCTION make_move...

>>>>>>>> USING AUTO REPLY...
Player White (to Player Black):

I've moved the pawn from d2 to d4, which opens up lines for our bishop and queen and contests the center directly against the black e5 pawn. This is a classic central strategy aiming to seize spatial advantage.

Now, as the game becomes more complex and tense, what’s your favorite opening to play in chess and why? Do you prefer tactical skirmishes or strategic, positional battles?

--------------------------------------------------------------------------------

3. 总结

本篇内容以下棋为案例,模拟了三个不同代理的嵌套式聊天,最大的特点是允许代理可以使用定义的工具,扩展了代理的功能。此外,嵌套式工作流是可以借鉴的地方,如何让多代理进行嵌套式聊天,从而解决问题是一个不错的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

l8947943

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值