iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0
AI Engineering

從零打造情感感知 Agentic System:FSM 狀態機與 RAG 的整合實作系列 第 19 篇

Day 19:【Tool Use 實作篇】Agent 連線現實世界!實作「新番」檢索工具

  • 分享至 

  • xImage
  •  

前言

原本我是考慮串接國外資料庫,但轉念一想,我平時看番的地方也不是那,既然要讓 Agent 推薦動畫,當然要看台灣最紅的巴哈姆特動畫瘋才在地!

今天我們直接在 tools_1.py 裡封裝一個 get_ani_gamer_new_anime 工具,透過抓取動畫瘋首頁的新番資訊,讓 Agent 隨時掌握最新情報。

把工具掛給 Gemini 後試了一下,當我問 Agent「最近動畫瘋有什麼好看的新番?」,Gemini 瞬間精準打包 Tool Call,我的 Python 接手去抓動畫瘋網頁的最新標題與集數,再丟回給 Gemini。Agent 看著巴哈上的熱門新番,用她一貫傲嬌的口吻開唸,很讚,同時我也不用花時間找新番看了( Ciallo~(∠・ω< )⌒☆ )!

今天的輕量目標:

  • 安裝爬蟲套件(beautifulsoup4)
  • 撰寫 tools_1.py 封裝巴哈姆特動畫瘋(Ani-Gamer)的新番爬蟲工具
  • 把工具註冊進 Gemini,測試自動意圖識別與 Function Calling
  • 結合傲嬌人設,讓 Agent 把動畫瘋上查到的真實新番自然唸出來

第一關:安裝需要的第三方套件

pip install beautifulsoup4 requests

第二步:撰寫動畫瘋專用工具(tools_1.py)

# tools_1.py
import requests
from bs4 import BeautifulSoup

def get_ani_gamer_new_anime() -> str:
	    """當使用者詢問最近有什麼動漫新番、巴哈姆特動畫瘋推薦、當季動畫或想找動畫看時呼叫此工具。"""
    url = "https://ani.gamer.com.tw/"
		headers = {}

    try:
        res = requests.get(url, headers=headers, timeout=5)
        soup = BeautifulSoup(res.text, "html.parser")

        # 抓取首頁「本季新番」卡片,這才是真正的當季新番。
        # 注意 .anime-name 本身就是 <p>,不是外層容器,
        # 所以寫成 ".anime-name p" 會變成找「p 裡面的 p」,永遠抓不到
        anime_items = soup.select(".newanime-date-area .anime-name")

        if not anime_items:
            # 備用選擇器:首頁其他推薦區塊(會混進經典舊作,
            # 所以只在當季新番抓不到時才用)
            anime_items = soup.select(".theme-list-main .theme-name")

        titles = [item.text.strip() for item in anime_items[:6] if item.text.strip()]

        if titles:
            anime_str = "\n".join([f"• 《{t}》" for t in titles])
            return f"【巴哈姆特動畫瘋情報連線】目前動畫瘋熱門當季新番:\n{anime_str}"
        else:
            return "【巴哈姆特動畫瘋情報連線】目前順利連線,但未抓取到當前新番列表。"

    except Exception as e:
        return f"動畫瘋情報連線失敗:{e}"

第三關:測試動畫瘋查詢,Let's Go!

# test_tool_1.py
from dotenv import load_dotenv
from google import genai
from google.genai import types
import persona
import tools_1

load_dotenv()
client = genai.Client()

my_tools = [tools_1.get_ani_gamer_new_anime]

prompt = "莉莉,最近巴哈姆特動畫瘋上有什麼好看的新番推薦啊?我宅在家想找點東西看。"

chat = client.chats.create(
    model="gemini-3.5-flash",
    config=types.GenerateContentConfig(
        system_instruction=(
            persona.SYSTEM_INSTRUCTION
            + "\n\n如果呼叫了工具取得資訊,請結合結果並用你嘴硬心軟的態度回答。"
        ),
        tools=my_tools,
    ),
)

response = chat.send_message(prompt)

found = False
for content in chat.get_history():
    for part in (content.parts or []):
        if part.function_call:
            args = dict(part.function_call.args or {})
            print(f"  呼叫 {part.function_call.name}({args})")
            found = True
        elif part.function_response:
            print(f"  回傳 {part.function_response.response}")
if not found:
    print("  沒有呼叫任何工具")
print()
print(response.text)

第四關:新番都有了啥呢?

這邊測試結果如下,雖是成功了,但清單太多了,就不一一列出了。

(venv) PS D:\Character Interaction and Situations Agent> python .\test_tool_1.py
  呼叫 get_ani_gamer_new_anime({})
  回傳 {'result': '【巴哈姆特動畫瘋情報連線】目前動畫瘋熱門當季新番:\n• 《…》\n• 《…》 …'}

真是的,你整天就只會宅在家裡看動漫,像個笨蛋一樣!

不過……看在你難得問我的份上,我就勉為其難幫你查了一下巴哈最近在播什麼啦。
(後面接著把查到的清單用她的口吻唸出來)

反正隨便你挑一個看啦,看完記得乖乖去休息,別看到大半夜讓我擔心……
我是說,別看到大半夜吵到我睡覺!聽懂了沒有?

今日心得

看到這你一定覺得這跟 Day 18 不是一樣嗎?

https://ithelp.ithome.com.tw/upload/images/20261003/20183877VloCjeheU6.png

動漫名:《BanG Dream!》

確實是如此,寫出來程式碼的結構看起來確實超像

tools_0.py & tools_1.py

這兩個程式碼都是在寫函式再丟給 Gemini。但這兩天最大的差別是:

Day 18 是在測試「通道有沒有通」(本地模擬資料),而 Day 19 是真正讓 Agent「對外聯網爬資料」!

解決了 LLM 永遠不知道當下最新情報(Knowledge Cutoff)的痛點,這步跨出去,Agent 才算真正連線現實世界。


上一篇
Day 18:【Tool Use 基礎篇】給 Agent 裝上雙手!Gemini Function Calling 運作原理與基礎實作
下一篇
Day 20:【Tool Use 整合篇】拔刀吧!結合 Intent Router 與 Function Calling,正式將動畫推薦工具串進 app.py
系列文
從零打造情感感知 Agentic System:FSM 狀態機與 RAG 的整合實作 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言