使用 AutoGen 設計 AI 工作流程

隨著人工智慧(AI)的不斷發展,代理式 AI 應運而生,旨在解決不同場景下的複雜工作流程問題。AutoGen 是一個具備決策制定和處理複雜工作流程能力的框架。欲了解更多關於 AutoGen 框架的資訊,請參閱《使用 AutoGen 框架構建您的第一個代理式 AI》。在本篇文章中,我們將學習如何在 AutoGen 的支持下,以不同的方式設計工作流程。我們將從一個簡單的工作流程開始,進行算術運算。

理解代理式 AI 工作流程

代理式 AI 工作流程指的是一種類型的工作流程或過程,結合使用 AI 系統來執行傳統由人類完成的任務,例如客戶服務。借助於代理式 AI,其具備理解複雜任務並自主達成目標的能力,幾乎不需要人類干預,這樣人類專家可以從重複性枯燥的任務中解放出來。同時,強大的計算能力也能提升工作效率。請訪問本博客的《代理式 AI 介紹》以進一步了解代理式 AI。

使用 AutoGen 代理進行算術運算

在本博客中,我們將首先以算術運算為例,開始一個較為簡單的工作流程。我們通常可以通過三種方式執行算術運算:使用順序流程、使用群聊類別或使用工具。請參閱本博客以了解使用 AutoGen 框架的基本設置,但這次我們使用的是 GPT-4 而非 3.5 turbo,以確保更好的輸出。

使用多代理的順序流程

此範例改編自 AutoGen 的對話模式

我們首先設置 5 個代理。一個代理(number_agent)負責整個流程控制,其他四個代理分別執行四種算術運算。

number_agent = ConversableAgent(
    name="Number_Agent",
    system_message="請將我提供的數字按行返回給我,每行一個數字。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
adder_agent = ConversableAgent(
    name="Adder_Agent",
    system_message="請將我提供的每個數字加 2,並按行返回新數字。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
multiplier_agent = ConversableAgent(
    name="Multiplier_Agent",
    system_message="請將我提供的每個數字乘以 2,並按行返回新數字。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
subtracter_agent = ConversableAgent(
    name="Subtracter_Agent",
    system_message="請將我提供的每個數字減去 2,並按行返回新數字。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
divider_agent = ConversableAgent(
    name="Divider_Agent",
    system_message="請將我提供的每個數字除以 2,並按行返回新數字。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)

預設情況下, carryover 會累積並攜帶來自先前聊天結果的所有上下文,如 AutoGen 教程中的範例所示。因此,我們創建了自己的消息處理函數,以便僅將一個數字傳遞到下一個聊天。

def my_message(sender: ConversableAgent, recipient: ConversableAgent, context: dict):
    carryover = context.get("carryover", "")
    if isinstance(carryover, list):
        carryover = carryover[-1]
    final_msg = "這是我的數字\n上下文:\n" + carryover
    return final_msg

然後,我們會執行 initiate_chats 以預先設定的順序 (加法器、乘法器、減法器、除法器) 來啟動多次聊天。我們會從第二個聊天開始使用 my_message 函式,讓 number_agent 只將最終的數字提供給下一個代理,而不是所有經過聊天的結果。

chat_results = number_agent.initiate_chats(
    [
        {
            "recipient": adder_agent,
            "message": "14",
            "max_turns": 1,
            "summary_method": "last_msg",
            "clear_history": True,
        },
        {
            "recipient": multiplier_agent,
            "message": my_message,
            "max_turns": 1,
            "summary_method": "last_msg",
            "clear_history": True,
        },
        {
            "recipient": subtracter_agent,
            "message": my_message,
            "max_turns": 1,
            "summary_method": "last_msg",
            "clear_history": True,
        },
        {
            "recipient": divider_agent,
            "message": my_message,
            "max_turns": 1,
            "summary_method": "last_msg",
            "clear_history": True,
        },
    ]
)

輸出:

********************************************************************************
開始新的聊天....
********************************************************************************
Number_Agent (to Adder_Agent):

14

--------------------------------------------------------------------------------
Adder_Agent (to Number_Agent):

16

--------------------------------------------------------------------------------
********************************************************************************
開始新的聊天....
********************************************************************************
Number_Agent (to Multiplier_Agent):

這是我的數字
上下文:
16

--------------------------------------------------------------------------------
Multiplier_Agent (to Number_Agent):

32

--------------------------------------------------------------------------------
********************************************************************************
開始新的聊天....
********************************************************************************
Number_Agent (to Subtracter_Agent):

這是我的數字
上下文:
32

--------------------------------------------------------------------------------
Subtracter_Agent (to Number_Agent):

30

--------------------------------------------------------------------------------
********************************************************************************
開始新的聊天....
********************************************************************************
Number_Agent (to Divider_Agent):

這是我的數字
上下文:
30

--------------------------------------------------------------------------------
Divider_Agent (to Number_Agent):

15

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

為了方便測試,您可以使用以下代碼對不同數字進行測試,並使用上述預定義的運算。設置和代理與上述相同。以下代碼新增了參數 “silent” 以隱藏聊天並僅打印運算結果。

def predefined_operation(input):
    chat_results = number_agent.initiate_chats(
        [
            {
                "recipient": adder_agent,
                "message": input,
                "max_turns": 1,
                "summary_method": "last_msg",
                "silent":True,
                "clear_history": True,
            },
            {
                "recipient": multiplier_agent,
                "message": my_message,
                "max_turns": 1,
                "summary_method": "last_msg",
                "clear_history": True,
                "silent":True,
            },
            {
                "recipient": subtracter_agent,
                "message": my_message,
                "max_turns": 1,
                "summary_method": "last_msg",
                "clear_history": True,
                "silent":True,
            },
            {
                "recipient": divider_agent,
                "message": my_message,
                "max_turns": 1,
                "summary_method": "last_msg",
                "clear_history": True,
                "silent":True,
            },
        ]
    )
    return chat_results

def arithmetic_sequential_chat(): 
    print("歡迎使用算術聊天機器人!") 
    while True: 
        user_input = input("輸入一個數字以執行預定義的算術運算或輸入 'exit' 退出: ") 
        if user_input.lower() == 'exit': break 
        try: 
            num = eval(user_input)
            if(isinstance(num,int) or isinstance(num,float)):
                chat_results = predefined_operation(user_input)
                print(f"結果: {chat_results[-1].summary}") 
            else: print("請輸入一個整數或浮點數,或輸入 exit.")
        except Exception as e: print(f"錯誤: {e}") 
        print()

if __name__ == "__main__":
    arithmetic_sequential_chat()

然而,使用順序聊天時,AI 只能按照定義的順序對輸入數字進行算術運算。它無法解決像 1+4/2 這樣的方程式。因此,我們必須使用另一種方法來實現方程式的求解。

使用群聊進行計算

群聊是一種創建更通用對話模式的類別,涉及兩個以上的代理。它允許所有代理共同參與單一對話線程,並由另一個名為群聊管理員的代理共享相同的上下文。使用群聊的整體流程將在下圖中說明。

credit, AutoGen

我們將設置與上述部分類似的代理(Number_Agent、Adder_Agent、Multiplier_Agent、Subtracter_Agent、Divider_Agent),但會添加額外的描述。描述是為了讓其他代理如群聊管理員了解每個代理的職責,並可能用作選擇下一位說話者的參考。預設輸入是代理的 system_message。

number_agent = ConversableAgent(
    name="Number_Agent",
    system_message= "請以數字轉換開始對話,並在轉換完成後返回 '終止'。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
adder_agent = ConversableAgent(
    name="Adder_Agent",
    system_message="請將我提供的最後一個數字加 1,並返回新數字,每行一個數字。"
                     "僅執行一個運算。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
multiplier_agent = ConversableAgent(
    name="Multiplier_Agent",
    system_message="請將我提供的最後一個數字乘以 2,並返回新數字,每行一個數字。"
                     "僅執行一個運算。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
# Subtracter Agent 將從接收到的每個數字中減去 1。
subtracter_agent = ConversableAgent(
    name="Subtracter_Agent",
    system_message="請將我提供的最後一個數字減 1,並返回新數字,每行一個數字。"
                     "僅執行一個運算。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
divider_agent = ConversableAgent(
    name="Divider_Agent",
    system_message="請將我提供的最後一個數字除以 2,並返回新數字,每行一個數字。"
                     "若最後一個數字不是偶數,請勿執行除法。"
                     "僅執行一個運算。",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
adder_agent.description = "將最後一個輸入數字加 1。"
multiplier_agent.description = "將最後一個輸入數字乘以 2。"
subtracter_agent.description = "將最後一個輸入數字減 1。"
divider_agent.description = "將最後一個輸入數字除以 2。如果最後一個數字不是偶數,請勿執行除法。"
number_agent.description = "轉換完成後終止對話。"

接著我們要設定群聊物件。此物件包含 3 個參數,包括 agents, messages, 和 speaker_selection_method

from autogen import GroupChat
group_chat = GroupChat(
    agents=[adder_agent, multiplier_agent, subtracter_agent, divider_agent,
            number_agent],
    messages=[],
    speaker_selection_method=custom_speaker_selection_func
)

如名稱 speaker_selection_method 所示,這指的是群聊如何選擇下一位發言者來生成回覆。預設為 “auto”,即由群聊管理員的語言模型(LLM)選擇發言者。在上述範例中,我們選擇使用自定義方法,允許在接收到來自 number_agent 的 “終止” 消息時結束對話。

def custom_speaker_selection_func(last_speaker, groupchat):
    messages = groupchat.messages
    if last_speaker == number_agent:
        if "TERMINATE" in messages[-1]["content"]:
            return None
    return "auto"

要使用群聊對象,我們需要一個特殊的代理,群聊管理員。此管理員代理不參與聊天,而是管理聊天流程。欲了解更多關於群聊和群聊管理員的信息,請參閱 AutoGen 網站的相關頁面

from autogen import GroupChatManager
group_chat_manager = GroupChatManager(
    groupchat=group_chat,
    llm_config=llm_config,
)

最後,我們可以通過與管理員啟動聊天來生成群聊結果。

chat_result = number_agent.initiate_chat(
    group_chat_manager,
    message="我的數字是 4,我想將它轉換為 9。",
    summary_method="reflection_with_llm",
)

輸出:

Number_Agent (to chat_manager):

我的數字是 4,我想將它轉換為 9。

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

Next speaker: Multiplier_Agent

Multiplier_Agent (to chat_manager):

8

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

Next speaker: Adder_Agent

Adder_Agent (to chat_manager):

9

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

Next speaker: Number_Agent

Number_Agent (to chat_manager):

TERMINATE

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

您還可以使用以下代碼,使用與上述相同的代理對不同的輸入進行操作。

def groupChat(start:int,end:int):
    chat_result = number_agent.initiate_chat(
        group_chat_manager,
        message=f"My number is {start}, I want to turn it into {end}.",
        summary_method="reflection_with_llm",
        clear_history=True,
    )
    return chat_result

def arithmetic_groupChat():
    print("Welcome to the arithmetic chatbot!") 
    while True: 
        user_input1 = input("Enter two integers a,b to find a way to convert a to b by simple arithmetic operation or 'exit' to quit: ") 
        if user_input1.lower() == 'exit': break
        user_input2 = input()
        if user_input2.lower() == 'exit': break

        try: 
            num1 = eval(user_input1)
            num2 = eval(user_input2)
            if(isinstance(num1,int) or isinstance(num2,int)):
                chat_result = groupChat(user_input1, user_input2)
                adder_agent.clear_history()
                subtracter_agent.clear_history()
                divider_agent.clear_history()
                multiplier_agent.clear_history()
                number_agent.clear_history()
                group_chat_manager.clear_history()

            else: print("Please input integers or exit.")
        except Exception as e: print(f"Error: {e}") 
        print()

if __name__ == "__main__":
    arithmetic_groupChat()

通過上述群聊,我們可以讓管理員代理選擇下一位發言者,而不是使用預定順序。這提供了變化,允許代理們執行運算以將一個數字轉換為另一個數字。然而,這仍然無法對帶有方程式的算術運算進行操作。因此,我們將介紹第三種方法,使用工具來實現此目標。

使用工具進行計算

除了群聊之外,我們還可以簡單地使用計算工具來執行算術運算。工具是代理在註冊後可以調用的預定義函數。這些工具可能包括網絡搜索、執行計算、讀取文件等。本次我們使用其來執行計算。代碼改編自 AutoGen 的工具使用教程。

首先,我們將定義一個計算器工具:

from typing import Annotated, Literal, Union

Operator = Literal["+", "-", "*", "/"]

def calculator(a: Union[int,float], b: Union[int,float], operator: Annotated[Operator, "operator"]) -> int:
    if operator == "+":
        return a + b
    elif operator == "-":
        return a - b
    elif operator == "*":
        return a * b
    elif operator == "/":
        return a / b
    else:
        raise ValueError("Invalid operator")

然後,我們將設置兩個 Conversable Agent。一個作為助手決定運算順序,另一個作為用戶。

assistant = ConversableAgent(
    name="Assistant",
    system_message="你是一个有帮助的 AI 助手。"
                   "你可以协助进行简单的计算。"
                   "任务完成后返回 '終止'。",
    llm_config=llm_config,
)
user_proxy = ConversableAgent(
    name="User",
    llm_config=False,
    is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"],
    human_input_mode="NEVER",
)

接著,我們需要將計算器註冊給這兩個代理。在此範例中,助理將決定函數的輸入,而 user_proxy 將使用工具。因此,user_proxy 不需要 LLM,因為它只用作簡單計算器的執行者。

register_function(
    calculator,
    caller=assistant,
    executor=user_proxy,
    name="calculator",
    description="一個簡單的計算器,包含四種運算符 '+'(加法)、'-'(減法)、'*'(乘法)和 '/'(除法),輸入兩個數字作為參數。",
)

最後,您可以通過初始化兩個代理之間的聊天來執行運算。

chat_result = user_proxy.initiate_chat(assistant, message="What is (2 + 3 / (4 - 5)) * 6?")

輸出:

User (to Assistant):

What is (2 + 3 / (4 - 5)) * 6?

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

>>>>>>>> USING AUTO REPLY...
Assistant (to User):

***** Suggested tool call (call_sOqa4IrsVF6m4Y8mYS1h2FDO): calculator *****
Arguments: 
{
  "a": 4,
  "b": 5,
  "operator": "-"
}
***************************************************************************

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

>>>>>>>> EXECUTING FUNCTION calculator...
User (to Assistant):

User (to Assistant):

***** Response from calling tool (call_sOqa4IrsVF6m4Y8mYS1h2FDO) *****
-1
**********************************************************************

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

>>>>>>>> USING AUTO REPLY...
Assistant (to User):

***** Suggested tool call (call_oVboqCgA0NyNXPjCaC776AKC): calculator *****    
Arguments:
{
  "a": 3,
  "b": -1,
  "operator": "/"
}
***************************************************************************    

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

>>>>>>>> EXECUTING FUNCTION calculator...
User (to Assistant):

User (to Assistant):

***** Response from calling tool (call_oVboqCgA0NyNXPjCaC776AKC) *****
-3.0
**********************************************************************

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

>>>>>>>> USING AUTO REPLY...
Assistant (to User):

***** Suggested tool call (call_Gj98oGkSAwPLd1ggkVVyqG55): calculator *****    
Arguments: 
{
  "a": 2,
  "b": -3,
  "operator": "+"
}
***************************************************************************    

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

>>>>>>>> EXECUTING FUNCTION calculator...
User (to Assistant):

User (to Assistant):

***** Response from calling tool (call_Gj98oGkSAwPLd1ggkVVyqG55) *****
-1
**********************************************************************

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

>>>>>>>> USING AUTO REPLY...
Assistant (to User):

***** Suggested tool call (call_bNTkqZd6kZFpBfvYy7TPrQdf): calculator *****    
Arguments:
{
  "a": -1,
  "b": 6,
  "operator": "*"
}
***************************************************************************    

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

>>>>>>>> EXECUTING FUNCTION calculator...
User (to Assistant):

User (to Assistant):

***** Response from calling tool (call_bNTkqZd6kZFpBfvYy7TPrQdf) *****
-6
**********************************************************************

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

>>>>>>>> USING AUTO REPLY...
Assistant (to User):

The result of the calculation (2 + 3 / (4 - 5)) * 6 is -6.

TERMINATE

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

您還可以使用以下代碼對不同輸入進行測試:

def arithmetic_tool():
    print("歡迎使用算術聊天機器人!")
    while True:
        user_input1 = input("輸入一個算術運算,例如 (2 + 3 / (4 - 5)) * 6,或輸入 'exit' 退出: ")
        if user_input1.lower() == 'exit':
            break
        try:
            expression = eval(user_input1)
            if isinstance(expression, int) or isinstance(expression, float):
                chat_result = user_proxy.initiate_chat(assistant, message=f"What is {user_input1}?")
        except Exception as e:
            print(f"錯誤: {e}")
        print()

if __name__ == "__main__":
    arithmetic_tool()

結論

在本篇文章中,我們學會了如何利用 AutoGen 提供的不同代理或功能來執行算術運算,作為使用 AutoGen 代理之旅的起點。希望您能理解如何從教程中設置一個簡單的工作流程,並能進一步探索 AutoGen 以創建更複雜的工作流程,例如編寫和執行代碼。

附加資源

以下是來自 AutoGen 網站的一些附加資源,供您參考或感興趣時使用,如果您想了解更多 AutoGen 的功能。

Discover more from OpenAPIHub 社群

Subscribe now to keep reading and get access to the full archive.

Continue reading