OpenAPIHub 社群

使用 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 的功能。

Exit mobile version