在上一篇中,我們已經完成了 飯店搜尋 Agent,可以根據城市查詢飯店資訊。
接下來,我們要進一步完成 飯店比較 Agent,可以針對兩間指定飯店,比較價格或評價,並輸出推薦結果。
這支 Agent 也會先使用 FastAPI 來模擬行為,方便之後轉換成 ADK Sub-Agent。
這個 Agent 的功能主要有:
cheapest
:比較哪一間價格較便宜best_rating
:比較哪一間評價較高(星級)注意:這裡使用 模擬資料庫,不會串接真實 API。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from typing import List, Literal
app = FastAPI(
title="飯店比較 Agent API",
description="使用 Pydantic 的版本,可比較兩間飯店的價格或評價並輸出結論。",
version="2.0.0",
)
# 模擬飯店資料庫
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},
],
}
先建立一個簡單的資料庫,方便模擬查詢。
Pydantic 可以幫助我們驗證輸入資料的型別與格式:
class CompareRequest(BaseModel):
hotel_names: List[str] = Field(..., min_items=2, max_items=2, example=["Hotel A", "Hotel B"])
criterion: Literal["cheapest", "best_rating"] = Field(
"cheapest", description="比較條件,可選 'cheapest' 或 'best_rating'"
)
hotel_names
:必須提供兩間飯店criterion
:比較條件,可選價格最便宜 (cheapest
) 或評價最高 (best_rating
)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
。
@app.post("/compare_hotels")
def compare_hotels(request: CompareRequest):
"""
呼叫飯店比較 Agent。
功能:
- 輸入兩間飯店名稱
- 從資料庫搜尋資料
- 比較「最便宜」或「最佳評價」
- 最便宜輸出結論:「哪一間 < 哪一間」
- 最佳評價的輸出結論:「哪一間 > 哪一間」
"""
try:
hotel1_name, hotel2_name = request.hotel_names
criterion = request.criterion
hotel1 = find_hotel_by_name(hotel1_name)
hotel2 = find_hotel_by_name(hotel2_name)
if not hotel1 or not hotel2:
missing = [n for n, h in zip(request.hotel_names, [hotel1, hotel2]) if h is None]
raise HTTPException(status_code=404, detail=f"Hotel(s) not found: {', '.join(missing)}")
if criterion == "cheapest":
if hotel1["price"] == hotel2["price"]:
comparison = f"{hotel1['name']} 與 {hotel2['name']} 價格相同 ({hotel1['price']} = {hotel2['price']})"
better = hotel1
else:
better = min([hotel1, hotel2], key=lambda x: x["price"])
worse = hotel2 if better == hotel1 else hotel1
comparison = f"{better['name']} 的價格較便宜 ({better['price']} < {worse['price']})"
elif criterion == "best_rating":
if hotel1["stars"] == hotel2["stars"]:
comparison = f"{hotel1['name']} 與 {hotel2['name']} 評價相同 ({hotel1['stars']} stars = {hotel2['stars']} stars)"
better = hotel1
else:
better = max([hotel1, hotel2], key=lambda x: x["stars"])
worse = hotel2 if better == hotel1 else hotel1
comparison = f"{better['name']} 評價較高 ({better['stars']} stars > {worse['stars']} stars)"
return {
"status": "success",
"criterion": criterion,
"hotels_compared": [hotel1, hotel2],
"comparison_result": comparison,
"recommended_hotel": better,
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
cheapest
:找價格低的飯店best_rating
:找評價高的飯店hotels_compared
:兩間飯店詳細資料comparison_result
:文字結論recommended_hotel
:推薦飯店