iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
生成式 AI

Multi-Agent 實戰:開發多代理智慧小幫手系列 第 21

【Day 21】 小專案 - 飯店比較 Agent(下)

  • 分享至 

  • xImage
  •  

上一篇我們已經完成 API 的撰寫了,接下來要把它改寫成 Sub-Agent

改為 Agent

首先,我們要把原本的 FastAPI 函式改寫成 可被 ADK 調用的 Agent

  1. 匯入模組 與 prompt.py 並建立資料庫

    from fastapi import HTTPException
    from google.adk.agents import Agent
    from . import prompt
    
    HOTEL_DATABASE = {
        "Taipei": [
            {"name": "Taipei Grand Hotel", "stars": 5, "price": 4000},
            {"name": "Hotel Proverbs Taipei", "stars": 4, "price": 3000},
            {"name": "Cosmos Hotel Taipei", "stars": 3, "price": 2000},
            {"name": "Caesar Park Hotel", "stars": 4, "price": 3500},
        ],
        "Tokyo": [
            {"name": "Park Hyatt Tokyo", "stars": 5, "price": 50000},
            {"name": "Shinjuku Granbell Hotel", "stars": 4, "price": 20000},
            {"name": "Hotel Sunroute Plaza", "stars": 3, "price": 15000},
        ],
        "New York": [
            {"name": "The Plaza", "stars": 5, "price": 700},
            {"name": "Pod 51 Hotel", "stars": 3, "price": 200},
            {"name": "Arlo SoHo", "stars": 4, "price": 350},
        ],
    }
    
  2. 建立搜尋工具函式
    它可以在資料庫中找到指定的飯店。

    def find_hotel_by_name(name: str):
        for city, hotels in HOTEL_DATABASE.items():
            for hotel in hotels:
                if hotel["name"].lower() == name.lower():
                    return hotel
        return None
    

功能:遍歷所有城市,找到名稱符合的飯店。
找不到就回傳 None。

  1. Sub-Agent 的工具函式(Tool Function)
    接著,我們把原本的 API 改成可以被 Agent 調用的「工具函式」。
    def compare_hotels(request: dict) -> dict:
        """
        呼叫飯店比較 Agent,支援「最便宜」或「最佳評價」比較
        """
        try:
            hotel_names = request.get("hotel_names", [])
            criterion = request.get("criterion", "cheapest").lower()
    
            if not hotel_names or len(hotel_names) != 2:
                raise ValueError("Please provide exactly two hotel names in 'hotel_names'.")
    
            hotel1 = find_hotel_by_name(hotel_names[0])
            hotel2 = find_hotel_by_name(hotel_names[1])
    
            if not hotel1 or not hotel2:
                missing = [n for n, h in zip(hotel_names, [hotel1, hotel2]) if h is None]
                raise ValueError(f"Hotel(s) not found in database: {', '.join(missing)}")
    
            if criterion == "cheapest":
                if hotel1["price"] == hotel2["price"]:
                    comparison = f"{hotel1['name']} 與 {hotel2['name']} 價格相同 ({hotel1['price']} = {hotel2['price']})"
                    recommended = hotel1
                else:
                    recommended = min([hotel1, hotel2], key=lambda x: x["price"])
                    worse = hotel2 if recommended == hotel1 else hotel1
                    comparison = f"{recommended['name']} 的價格較便宜 ({recommended['price']} < {worse['price']})"
            elif criterion == "best_rating":
                if hotel1["stars"] == hotel2["stars"]:
                    comparison = f"{hotel1['name']} 與 {hotel2['name']} 評價相同 ({hotel1['stars']}★ = {hotel2['stars']}★)"
                    recommended = hotel1
                else:
                    recommended = max([hotel1, hotel2], key=lambda x: x["stars"])
                    worse = hotel2 if recommended == hotel1 else hotel1
                    comparison = f"{recommended['name']} 評價較高 ({recommended['stars']}★ > {worse['stars']}★)"
            else:
                raise ValueError("Criterion must be 'cheapest' or 'best_rating'.")
    
            return {
                "status": "success",
                "criterion": criterion,
                "hotels_compared": [hotel1, hotel2],
                "comparison_result": comparison,
                "recommended_hotel": recommended,
            }
    
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"An error occurred: {e}")
    

功能摘要:

  • 從 request 中取出要比較的兩個飯店名稱與條件(價格或評價)
  • 進行比較並回傳結果
  • 相同評價時會回傳相同

Sub-Agent

hotel_compare_agent = Agent(
    name="hotel_compare_agent",
    model="gemini-2.5-flash",
    description=prompt.HOTEL_COMPARE_AGENT_DESCRIPTION,
    instruction=prompt.HOTEL_COMPARE_AGENT_INSTRUCTION,
    tools=[compare_hotels],
)

這樣一來,Master Agent(Root Agent)在接收到使用者說:
「請幫我比較 Taipei Grand Hotel 跟 Hotel Proverbs Taipei 哪一個比較便宜」時,就會自動調用這個 hotel_compare_agent。

簡易的 Prompt

Prompt 分成兩個部分:

  • description:描述這支 Agent 的任務內容,這裡是「負責比較兩家飯店」。

    HOTEL_COMPARE_AGENT_DESCRIPTION = """
    This is a hotel comparison sub-agent that compares two specified hotels and determines which one is better based on price or rating.
    """
    
  • instruction:詳細指令,告訴 Agent 該怎麼做。

    HOTEL_COMPARE_AGENT_INSTRUCTION = """
    You are a hotel comparison agent responsible for analyzing two hotels.
    
    Your responsibilities:
    - Accept exactly two hotel names and a comparison criterion ("cheapest" or "best_rating").
    - Retrieve hotel data from the internal database.
    - Compare the hotels based on the given criterion:
      - "cheapest": select the hotel with the lower price.
      - "best_rating": select the hotel with the higher star rating.
    - If both hotels have the same price or rating, clearly indicate this in your response.
    - Return:
      - hotels_compared: full information of both hotels
      - comparison_result: a textual summary of which hotel is better
      - recommended_hotel: the recommended hotel
    
    Ensure your recommendation is clear, precise, and includes the comparison details.
    """
    
    • prompt 的內容概述
      1. 輸入要求

        • 接收兩個飯店名稱(hotel_names)。
        • 接收比較條件(criterion):
          • cheapest:比價格(選擇較便宜的飯店)
          • best_rating:比評價(選擇評價較高的飯店)
      2. 執行流程

        • 從內部資料庫抓取兩間飯店資料。
        • 根據條件比較兩者。
        • 若兩間飯店的價格或評價相同,需在結果中清楚說明。
      3. 輸出格式

        • hotels_compared: 兩間飯店的完整資料(名稱、價格、星級)。
        • comparison_result: 文字說明哪一間較好與比較依據。
        • recommended_hotel: 最推薦的飯店資訊。
      4. 語氣與風格

        • 回覆需「清楚」、「具體」、「邏輯明確」。
        • 不得模糊描述或省略比較依據。

上一篇
【Day 20】 小專案 - 飯店比較 Agent(上)
系列文
Multi-Agent 實戰:開發多代理智慧小幫手21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言