[Python][Gemini CLI] 使用 LangChain 中的 Vertex AI 來處理 LINE Bot 中的圖片內容

image-20250305221818691

前情提要

之前 [Python] 在 LangChain 中將 Gemini 換成使用 Vertex AI 曾經有分享給大家該如何使用 LangChain 中的 Vertex AI 的相關功能。它具有以下的優點:

  • 如果你專案放在 GCP CloudRun ,不需要額外放 Gemini API Key。可以更安全處理自己程式碼的安全性。
  • 使用了 VertexAI 還有許多相關進階功能可以使用,之後也可以慢慢分享。

這一篇文章主要寫程式的部分都是使用 Gemini CLI :p ,但是有一些地方也跟大家講一下如何跟 AI 來溝通才能避免錯誤卡住。

範例程式碼:

https://github.com/kkdai/linebot-gemini-python (大家可以參考 )

(透過這個程式碼,可以快速部署到 GCP Cloud Run)

關於 Vertex AI 上面使用 Gemini 來做圖形偵測的架構圖

image-20250728100915757

這一張網路的圖解釋得很清楚,這邊要記得由於 VertexAI 使用到 Gemini 圖片相關處理的時候,必須要使用到 GCS (Google Cloud Storage) ,所以你不能只是放某個網路圖片網址給他,而是必須要將圖片放入 Google Cloud Storage 的 Bucket 之中,才能處理。

這裡程式碼會有一些相關的修改,就會有以下的相關部分來解釋:

如何將圖片上傳到 GCS

  • 記得先到 GCS 建立一個新的 Bucket ,並且把這個名稱保持下來。放在環境變數上。 (這裡使用 GOOGLE_STORAGE_BUCKET )
  • 由於我們偵測完圖片後,就不會再次使用到他,所以可以馬上從 GCS 刪除,避免不小心沒刪除到,然後記得到 Lifecycle 設定一天的生命週期。

image-20250728101738917

要小心 Gemini CLI 使用 LINE Bot 套件造成不段重複錯誤

這邊要小心,即便我的 Gemini CLI 已經有使用了 Contex7 這個 MCP Server ,使得 Gemini CLI 永遠會去讀取最新的套件資訊。但是有時候,還是會卡住,這邊舉一個例子:

Google Chrome 2025-07-28 10.23.28

這是一個 我請 Gemini CLI 直接去開發如何使用 LangChain 中的 Vertex AI 來直接將 LINE Bot 圖片直接放到 GCS (Refer commit)

這邊會發現,其中會發現,他從 line_bot_api.get_message_content(event.message.id) 取得的物件,一直無法成功的取得相關的 stream 資訊。這邊我大改跑了三~四次的 prompt 都無法成功,所以只好人工下來請他修改一下:

其實我本來有先複製正確的寫法,請他幫我順一下之後:

  message_content = await line_bot_api.get_message_content(event.message.id)

  # Asynchronously read all content chunks into a byte string
  image_bytes = b''
  async for chunk in message_content.iter_content():
      image_bytes += chunk

  # Create an in-memory binary stream from the bytes
  image_stream = BytesIO(image_bytes)
  # Reset the stream's pointer to the beginning for the upload function
  image_stream.seek(0)

他還是會把它改回去,我只好又一次的糾正他,這時候才會正確。

image-20250728103206712

這時候才會寫正確 (Refer commit) :

Google Chrome 2025-07-28 10.23.32

相關程式碼,放一下:

        elif (event.message.type == "image"):
            user_id = event.source.user_id
            print(f"Received image from user: {user_id}")

            message_content = await line_bot_api.get_message_content(
                event.message.id
            )

            # Asynchronously read all content chunks into a byte string
            image_bytes = b''
            async for chunk in message_content.iter_content():
                image_bytes += chunk

            # Create an in-memory binary stream from the bytes
            image_stream = BytesIO(image_bytes)
            # Reset the stream's pointer to the beginning for the upload
            image_stream.seek(0)

            file_name = f"{uuid.uuid4()}.jpg"
            gcs_uri = None
            # Default error message
            response = "抱歉,處理您的圖片時發生錯誤。"

            try:
                gcs_uri = upload_to_gcs(
                    image_stream, file_name, google_storage_bucket)
                if gcs_uri:
                    print(f"Image uploaded to {gcs_uri}")
                    response = generate_image_description(gcs_uri)
            finally:
                # Clean up the GCS file if it was uploaded
                if gcs_uri:
                    delete_from_gcs(google_storage_bucket, file_name)

            reply_msg = TextSendMessage(text=response)
            await line_bot_api.reply_message(
                event.reply_token,
                reply_msg
            )
        else:
            continue

由於 GCS 相關使用方式,都是直接使用,大家快速參考即可:

def upload_to_gcs(file_stream, file_name, bucket_name):
    """Uploads a file to the bucket."""
    try:
        storage_client = storage.Client()
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(file_name)

        blob.upload_from_file(file_stream, content_type='image/jpeg')

        # Return the GCS URI
        return f"gs://{bucket_name}/{file_name}"
    except Exception as e:
        print(f"Error uploading to GCS: {e}")
        return None

成果:

image-20250728105409436

[好書分享] 日本製造 ,幻想浪潮 (動漫、電玩、Hello Kitty、2Channel,超越世代的精緻創新與魔幻魅力)

日本製造,幻想浪潮
動漫、電玩、Hello Kitty、2Channel,超越世代的精緻創新與魔幻魅力
Pure Invention: How Japan's Pop Culture Conquered the World
作者: 麥特‧阿爾特  
原文作者: Matt Alt  

買書推薦網址:

前言:

這是 2025 年第 3 本讀完的書,最近讀完的書籍越來越少,可能也跟花比較多的時間在學習 Vibe Coding 有關。這本書我買了蠻久的,但是也是斷斷續續直到近期才將他看完。 雖然裡面的故事都蠻久以前的,但是有許多不為人知的歷史背景與相關的史地資料都相當的珍貴。

大綱

◆ 幻想傳遞道具 ◆
每個人都是明星──【卡拉OK裝置】
◎屬性:魅力+10
◎使用方法:第一代卡拉OK裝置需要先投入100日圓,拿起麥克風盡情發揮即可,效果持續一整首歌。

為自己的世界配樂──【隨身聽】
◎屬性:自我恢復力增加50%
◎使用方法:放入錄音帶、戴上耳機、按下播放鍵,無論走到哪裡,都能親手打造自己的背景音樂。

讓幻想跟著你走──【任天堂Game Boy】
◎屬性:MP回復加速
◎使用方法:走到哪玩到哪,還可以連線對戰。對了,這裡的連線指的是真的用「電線」連接兩台Game Boy。

召集各路英雄的所在──【2Channel討論區】
◎屬性:號召力+20,組隊作戰攻擊力+5
◎使用方法:日本最大的線上匿名布告欄系統,介面簡單,但造成的影響可不簡單,使用者遍佈全日本。

────────────────

● 最後提醒 ●
請記住!這不單單只是這些創造者個人勝利的故事,在創造者所賦予的力量下,包括你我在內的無數玩家與使用者,都意外地親身參與了整個過程,也成為這個幻想世界的眾多推動者之一。

是的,這精采華麗的世界是由我們一起建造的。

心得

這一本書有講到四個很有「歷史感」但是又很有意義的商品: 卡拉OK,隨身聽,任天堂跟討論區。

這四個其實也代表著四個日本從戰後嬰兒潮後的四個重要事物:

  • 卡啦OK拉攏著「朋友」,對應著日本的疏離感。
  • 隨身聽帶來的「音樂」,讓每個忙碌上班族放鬆的方式。
  • 任天堂帶來的「幻想」,讓壓抑日本人放鬆自我的空間。
  • 2Channel 帶來的「連結」,讓每個人可以匿名的發表自己的想法。

雖然是四個因素,但是也告訴我們許多當時日本社會下的現象。同時也感受到那個時代下的日本究竟有多少的創意與現實中的拉扯與衝突。 但是許多的產物都是很美好且難以抹滅的。 日本真的是造就了新的 ACG 世代之外,也有許多創作物讓世世代代的年輕人都難以忘記。

蠻有趣的一本書,很推薦大家來看。

[Gemini CLI] 用 Vibe Coding 打造你的專屬應用:我的 Gemini CLI 健身日誌實戰

Google Chrome 2025-06-25 22.05.23

前言

近期的開發圈,圍繞著「Vibe Coding」的討論不絕於耳,其中 Claude Code 的出現更是將這個概念推向了高峰。這是一種全新的開發典範,開發者透過對話與描述「感覺」來讓 AI 生成程式碼。在這波浪潮中,Google 也推出了自家的殺手級應用:Gemini CLI

本篇文章將分享我如何透過 Gemini CLI,從零開始打造一個個人化的健身日誌 Web App。你會發現,導入這種與 AI 協作的終端機工具後,開發流程不僅僅是加速,更是從根本上改變了我們與程式碼互動的方式。

本次的程式碼與成果

本次實作的專案是一個簡單的訓練日誌,最終成果如上圖所示。

專案 Repo:

快速複習 Vibe Coding

在深入 Gemini CLI 之前,我們先快速摘要一下「Vibe Coding」這個概念。傳統開發模式中,我們需要逐行撰寫精確的指令來建構應用程式。然而,Vibe Coding 讓我們能用更自然、更貼近人類思維的方式與 AI 協作。

開發者不再需要專注於每一行語法的細節,而是可以描述更高層次的目標,例如:

我需要一個深色主題、看起來專業的儀表板

或是

幫我建立一個 API 端點來記錄數據

AI 會理解這些意圖,並將其轉換為具體的程式碼與架構。Gemini CLI 正是實現這種開發模式的強大工具。

導入 Gemini CLI 實戰

Gemini CLI Screenshot

Gemini CLI: https://github.com/google-gemini/gemini-cli

Google 官方文章: https://blog.google/technology/developers/introducing-gemini-cli-open-source-ai-agent/

接下來,我們將拆解如何利用 Gemini CLI 來完成這個健身日誌專案。

第一部分:從 UI 概念到前端程式碼

一個專案的起點,往往是介面設計。在這個階段,我並沒有自己動手畫圖或寫 CSS,而是採用了以下的流程:

  1. 利用 AI Studio 產生 UI Layout:我先到 AI Studio,向它描述我想要的介面風格——簡潔、專注於資訊呈現、易於操作。AI 很快地提供了幾個視覺佈局供我參考。
  2. 生成 Tailwind CSS:在確定了喜歡的風格後,我請 AI Studio 將這個設計轉換成 Tailwind CSS 的格式。這是一個現代化的 CSS 框架,能讓我快速建構出美觀且響應式的介面,而我甚至不需要深入了解其語法細節。

可以看得出來,在專案初期,Gemini 生態系內的工具已經能幫助我們快速將模糊的想法具體化為可用的前端程式碼。

第二部分:了解 Gemini CLI 的運作大腦

有了前端的基礎後,接下來就是 Gemini CLI 大展身手的時刻。它不僅僅是一個程式碼生成器,更像是一個常駐在你終端機裡的資深開發夥伴。

它的強大之處在於:

  • 專案上下文理解:你只需要在專案目錄下啟動它,它就能夠掃描並理解整個專案的檔案結構與既有程式碼。
  • 整合開發工具鏈:它可以直接幫你執行 git 指令來進行版本控制,甚至能透過 gcloud 指令,將你的應用程式一鍵部署到 Cloud Run。
  • 建立自動化工作流:你可以和它建立「默契」。例如,我曾對它下達指令:

以後改完程式碼,都幫我 push 到 GitHub,然後直接跑一次本地端伺服器給我驗證。

從此,這個開發、測試、提交的循環就變得完全自動化且極其順暢。

Gemini CLI 的核心是將 Gemini 1.5 Pro 強大的模型能力與開發者熟悉的 CLI 環境深度整合,讓它能理解你的指令,並調用對應的工具來完成任務。

第三部分:根據實戰結果,來分析一下差異

導入 Gemini CLI 後,與傳統開發流程相比,最顯著的差異有兩點:

  1. 開發流程的無縫整合與自動化 以往,寫碼、測試、版本控制、部署是幾個獨立的步驟,需要手動切換工具與執行指令。但在 Gemini CLI 的輔助下,這些流程可以被串連成一個單一的對話指令。就像前面提到的,一個「改完就推送到 GitHub 並本地運行」的指令,就取代了過去繁瑣的手動操作,大幅提升了開發效率。

  2. 從抽象指令到具體成果的轉譯能力 傳統開發需要我們將需求拆解成非常具體的技術任務。但使用 Gemini CLI,我可以下達更為抽象的指令,例如「幫我把這個列表功能做出來」,它會自己分析現有程式碼,生成對應的邏輯並整合進去。它彌補了從「想法」到「程式碼」之間的巨大鴻溝。

超佛心的免費方案!

看到這裡,你可能會好奇這樣強大的服務是否所費不貲。Google 這次提供了極具誠意的免費方案!

只需使用個人 Google 帳戶登入,即可獲得免費的 Gemini Code Assist 授權。此授權包含:

  • 存取強大的 Gemini 1.5 Pro 模型
  • 高達 100 萬個 token 的龐大上下文視窗
  • 每分鐘 60 次模型請求
  • 每日 1,000 次免費請求

這個額度對於個人專案、學習或 POC 驗證來說,綽綽有餘,堪稱佛心!😍

未來的展望

本篇文章主要介紹了如何利用 Gemini CLI 這一新興工具,將 Vibe Coding 的概念應用於實戰,並成功打造出一個 Web App。可以預見,這類與 AI 深度整合的開發工具將會越來越普及。開發者的角色也將從「程式碼的撰寫者」逐漸轉變為「AI 協作的指揮者」。

接下來,我們或許可以探索更多 Gemini CLI 與 Google Cloud 生態系整合的複雜應用。期待這個工具能為開發者社群帶來更多的可能性,我們下次見。

[DevOps] Netflix 遊戲平台總監將解決技術債視為一種創新 - Tech debt as innovation by Bruce Wang

前提

好像是在 Threads 看到有人貼出的貼文,這明明是一個 25 分鐘的短篇演講。 但是我卻花了兩三個小時仔細的看他,並且不斷勾起我以前的回憶。 這是一篇 LeadDev 研討會的演講,主要內容探討到軟體開發人員最害怕的「技術債」(Technology Debt)。

Netflix的Bruce Wang分享技術負債管理經驗:技術負債是創新的自然產物,需建立共通語言與明確定義,公開討論並主動處理。技術負債管理得當可促進業務創新,推動公司成長。

相關內容分享

以下內容大多是針對某幾張投影片,做一些註解並且寫上自己的想法。

以下哪些不是 Tech Debt?

  • 商業決策(老闆不做的) - 沒有資源
  • 不同 model 間缺乏溝通
  • Bug. (很常~~懶得解就說是技術債)
  • Bad Code (寫的爛~也不會是技術債) - 效能問題 (效能問題絕對不是技術債)
  • 你對這些程式碼不熟…. (好像超多人講這個,好像重寫就沒有技術債一樣 XD)

image-20250610224541232

如何定義與描述「技術債」的準則:

定義上:

  • 最重要需要去研究你所謂的「技術債」究竟是什麼? 不能只是說一句,這是某個舊的框架,所以是個技術債。
  • 要「明確」,「可視化」並且「主動」去將技術債都找出並且明確的定義出來。

image-20250610224523232

對於「技術債」的處理方式:

精確的找到它,給它取個名字。

  • 某個 Tunnel 資訊流通上的限制 -> Tunnel X Project 不可以遇到事情,就說這是「技術債」。
  • 需要清楚的講出來是哪個技術債,不要把技術債當作是不想修復與不想處理上的籠統(suitcase)名詞。

image-20250610224459656

「Maintain/Improve 還是 Migrate?」

軟體開發流程上,許多軟體開發工程師往往接手舊的系統,到了要維護(或是優化)的狀況下,比較沒有經驗的人經常會選擇直接 migrate 到新的系統。 這往往是最有風險的事情,有太多危險可能發生:

  • 主管變動(忽然不想改)
  • 人員變動(又換了一組人)
  • 外在環境變動(生意忽然沒了? Covid 造成生意大好?)
  • 技術變動(AI 忽然跑出來)
  • 最大的風險是: 你根本不知道 Migrate 過去。

你所謂的技術債就會消失。 或許根本不會…. 你只會有一堆商業邏輯忘記搬過來。

image-20250610224439613

破解技術債的迷思

  • Legacy 不是 技術債,只是你沒花時間去搞懂他。
  • 技術債不需要全部清完,而是在必要時候去清除最重要的。
  • 技術債因為牽扯重要商業邏輯與更底層的技術,讓專業(資深)的來。
  • 技術債發生在任何產品中,新創產品其實更多。
  • 導入新的程式語言,新的框架,只會引來更多技術債。
  • 面對技術債,每一間公司都是有辦法來面對的。

image-20250610223511187

處理好技術債,面對更多商業挑戰

如果我們可以更有智慧,有積極的面對這些技術債,而不是天天將技術債作為不想維護的藉口。這樣我們才是認真面對這個商業服務,也才能更有信心的對接下來的商業需求說 “YES” 。

image-20250610224033292

後話

雖然是一個 25 分鐘的演講,但是我卻花了兩三個小時慢慢地欣賞跟品味每一段文字。 許多內容也呼應了身為軟體開發的心路歷程與以前的血淚(?)。 蠻推薦大家要好好思考這些相關的內容。

[n8n] 架設自有的 n8n 服務,讓資訊流串接的更好 (ifttt 取代方案)

Google Chrome 2025-06-01 13.05.03

前提:

本來一直有想要去學習 n8n ,但是還沒想到要拿來做什麼。近期去參加了 gai 年會之後,看到不少有趣的應用。決定回來先架起來試試看,本篇快速整理與分享一下近期看到幾個很有用的資訊。

還有我自己拿來做了什麼,希望對大家有幫助。

為什麼需要架設 n8n?

先分享一下,就我自己的為什麼需要架設自己的 n8n ? 還有他能幫助我什麼部分?

老實說,要架設「自動化服務」,很重要就是在於「自身的需求性」。我原本就有花錢買一些自動化服務 (ifttt) 加上透過自己的 LINE Bot 來打造自己的知識流的架構。

image-20250601160517764

大概是一個這樣的架構,其中 LINE Bot 工作還蠻 Heavy 的,需要爬下整個網頁內容,並且還要做 AI 摘要。

所以本來 IFTTT 經常會自動停掉。本來就有打算要移到 GCP,但是一個個寫成 CloudRun 又太費事,於是一直放著等待更好的解決方案的出現。 最近看到了 n8n ,決定來弄一下。 以下記錄一下我架設伺服器(免費),還有一些設定上需要注意的地方。

架設免費 n8n 伺服器 (HuggingFace + Supabase + Upstash)

這一篇可以看一下,對我幫助很大。總之先看看用量會不會不夠,再決定要不要放上 Google Cloud 。

比較需要注意的地方:

  • 大概就是 Supabase 的網址有多一個空白 ,這個真的很雷啊。雖然影片作者有講,但是還是被雷到。 XD

比較需要注意的整合部分:

這邊列出幾個我覺得在 n8n Node 串接上需要注意的:

記得將 Space 打開 Private ,不然不能串接 LINE 跟 TG (等等 POST Services)

安裝好的時候,一開始覺得 WebHook “GET” 沒問題就完事。結果發現 LINE Bot 一直串接不起來,才發現跟 Space 是隱藏的還是公開的有很大的關係。

記得去 Space -> Setting 將它打開。 (這樣就可以接 TG 跟 LINE Bot)

Google Chrome 2025-06-06 23.32.15

Google Sheet/Doc/Drive 串接

  • 可以參考同一位作者分享的這段影片,原來影片三個小時,但是可以跳到這個部分看就好。
  • 快速紀錄流程:
    • 進入 “Google Auth Platform”
    • 進入 “用戶端”
    • 增加一個 OAuth 的 “用戶端”
  • 需要注意的地方:
    • OAuth2 要串接,因為是測試帳號可能會小心失效。
    • 串接之前,務必要啟動 “Google Drive API”, “Googl Sheet API”, “Gmail API” 這幾個就平常架設 GCP 用戶比較少打開的。

JSON 檔案的處理

這部分算是 n8n 一個很重要的地方,很多時候你會需要使用 Edit Field(Set) Node 來處理。 沒有概念的,可以看這個部分影片

一些好用的 n8n 相關樣板:

取代掉原本 IFTTT 上面的一些服務

架設完畢也設定完相關的服務之後,就可以開始來取代掉 IFTTT 上面的服務。由於 IFTTT 本來就是比較簡單的 SaaS 服務,所以很快速的將相關的流程轉移到了 n8n 的服務上。

換過去之後,可以帶來的更多好處有:

  • 可以一步一步測試,避免因為某些 RSS 資料有問題,造成整個資訊流失敗。(IFTTT 就無法測試)
  • 可以增加更多資訊流的串接,我這裡串接了將每一次新的資料都寫在 Google Sheet ,可以之後做一些相關處理。

image-20250601170748669

總結

自動化可以幫助生活上解決很多重複性的工作,是每一個資訊工作者都需要的服務。而 n8n 我認為可以解決許多人生活上的大小困難事物。本篇文章提供一個比較簡單的架設方式,還有自身的問題解決思路。希望能給大家一些幫助,也希望每一個讀者可以儘早解決自己資訊流需要幫助的地方。

[Gemini][LINEBot] 輕鬆升級!從 Function Call 轉換為 Agent 模式的 ADK 實作指南

image-20250410202925234

前言

之前的文章曾經有分享過如何透過 Google ADK (Agent SDK) 來將你的 LINE 官方帳號 (俗稱: LINE Bot ) 打造成來。 但是其實在 LLM LINE Bot 上,我們有學過不少的 LLM 方式打造。本篇文章,將討論如何將 Function Calling 的 Agent 模式,直接改造成使用 Agent SDK 的方式。

你會發現這樣的修改,程式碼可以變得更精簡。而且由於導入了 Agent SDK ,整個對話也變得更加的靈活,更可以像是真人的對話。

本次的程式碼

本次將有兩個以往用過的程式碼:

快速複習 LangChain Function Call

各位可以參考一下本篇文章的詳細內容,這裡僅提供相關的快速摘要。

img

(這個是之前 LangChain Function Calling 的執行成果)

這篇文章介紹了如何利用 LangChain 和 OpenAI 的 Function Calling 來開發一個股價查詢的 LINE Bot,並分享了一個開源套件供大家學習。LangChain 是一個強大的工具,支援多種大型語言模型,讓開發概念驗證(POC)變得更加容易。文章中提到,透過 Flowise 這樣的視覺化工具,開發者可以快速測試架構和 Prompt,並且在不需要重新部署的情況下修改 Prompt。文章還詳細說明了如何在 Heroku 上快速部署 Python LINE Bot,並提供了使用 LangChain 的 ConversationBufferWindowMemory 來實現具有記憶功能的聊天機器人的方法。此外,文章深入探討了如何使用 OpenAI Functions 來查詢股價,包括如何定義和使用工具來實現這一功能。整體而言,這篇文章展示了 LangChain 在開發 LINE Bot 中的應用潛力,並鼓勵讀者利用這些技術打造出「專一」「好用」的聊天機器人。

image-20250531020759673

導入 Agent SDK

接下來會來開始拆解,如何將 LangChain Function Calling 的程式碼,轉換到 Agent SDK 的方式:

第一部分: 講解 Tools 的轉換方式:

我們先來討論一下,如何將 LangChain funciont Calling 中將 Tools 的程式碼,轉換到 Agent 的部分。

def get_price_change_percent(symbol: str, days_ago: int) -> dict:
    """
    Calculates the percentage change in a stock's price over a specified number of days.
    Args:
        symbol (str): The stock symbol (e.g., "AAPL").
        days_ago (int): The number of days to look back for the price change calculation. Must be positive.
    Returns:
        dict: Contains the symbol, percentage change, and period, or an error message.
    """
    if not isinstance(days_ago, int) or days_ago <= 0:
        return {"status": "error", "message": "Days ago must be a positive integer."}

    performance = calculate_performance(symbol, days_ago)
    if performance is not None:
        return {
            "status": "success",
            "symbol": symbol,
            "price_change_percent": performance,
            "period_days": days_ago,
        }
    else:
        return {
            "status": "error",
            "message": f"Could not calculate price change for {symbol} over {days_ago} days. Ensure symbol is valid and data is available for the period.",
        }

可以看得出來,大部分的程式碼並沒有太多修改。 但是主要就是之前在 Function Calling 的說明內容必須寫在這邊。才能讓 Agent 去正確的了解整個 Tools 的運作方式。

第二部分: 來了解整個 Agent 的運作大腦

接下來就要來看整個 Agent 如何去運用這三個工具?

root_agent = Agent(
    name="stock_agent",
    model="gemini-2.0-flash",  # Or your preferred model
    description="Agent specialized in providing stock market information and analysis.",
    instruction="""
        You are an AI assistant specializing in stock market data.
        Users will ask for stock prices, price changes, or the best performing stock from a list.
        Use the provided tools to answer these questions accurately.
        - For current price, use `get_stock_price`.
        - For price change percentage over a period, use `get_price_change_percent`.
        - For finding the best performing stock in a list over a period, use `get_best_performing`.
        Always state the symbol and the period clearly in your response if applicable.
        If a stock symbol is invalid or data is unavailable, inform the user clearly.
    """,
    tools=[
        get_stock_price,
        get_price_change_percent,
        get_best_performing,
    ],
)

這邊有稍微針對不同功能,來跟他解釋應該要呼叫哪個 tools 。但是這裡並不需要跟他解釋那些 tools 有什麼參數,還有回傳什麼資料。並且也不用跟他講解更多其他的資訊。

第三部分:根據實戰結果,來分析一下差異:

image-20250531165942006

有沒有發現兩個的差異在哪些地方:

1. 有了更深層的記憶能力,還有上下文的連貫

這部分主要跟 Agent 預設就有支援 Session Services 有關。透過 Session Services 整個 Agent 不光是記憶著之前的問題之外,還可以跟使用者達成一對一的聊天效果。這也是為什麼上面的聊天出現了

- 我: 其他兩個表現如何?
- Agent: 我很利益告訴你,但為了做到這一點,我需要分別查詢蘋果與超微的....

這樣就知道,他能理解整個對話 Context 中的「其他兩個」是代表什麼意思。這個也是相當的重要。

相關程式碼方式如下:

# Initialize InMemorySessionService
session_service = InMemorySessionService()
active_sessions = {}  # Cache for active session IDs per user

....

# Get or create a session for this user
session_id = await get_or_create_session(user_id)

以上兩個方式,就是主要負責記錄與處理 使用者交談對話匡的 Session_ID 處理的方式。

2. 在回答部分, Agent 變得更加聰明

以往在 Function Calling ,每一層對話本身是根據著使用者當下的問題來處理。就像前文提到的 「其他兩個表現如何?」是無法正確的執行。因為這個對話裡面的兩個,無法對應到 function calling 裡面的參數。

但是在 Agent 中,他不會強迫你每一次的呼叫一定要對應到一個 Function Calling 。而是發現需要使用到的時候,才會呼叫該 Function 的結果。

他會自動知道相關對話的內容,根據 Agent 剛剛定義的 prompt 流程去尋找需要的資料。很重要的是,就算沒有尋找到也會正常跑完一次的對話流程。

另外一個案例 Arxiv 論文小幫手改成 Agent 的案例

程式碼: https://github.com/kkdai/linebot-adk-arxiv

LINE 2025-05-31 02.00.46

image-20250531020215131

可以看得出來,類似的功能如果透過 Agent ADK 來達成的話。整個原本是 Function Call 的論文小幫手。就變得更加的聰明了,而且程式碼也沒有增加太多。這裡就不詳細解釋相關的功能了,歡迎各位直接去看程式碼。

未來的展望:

本篇文章主要介紹如何將原本使用 LangChain Function Calling 的 LINE Bot 轉換成使用 Agent SDK 的 LINE Bot 。這裡也看得出來,整體出來後的成果相當令人驚艷,不僅僅整個程式碼變得更少的之外,並且在對談中,也變得更加像真人一樣。接下來,我們將會深入 Agent 許多更加複雜的功能,比如說 Multiple Agent 與各種 Agent 中合作的方式。

也會透過 LINE Bot 的相關案例,來分享給每一個在 LINE 官方帳號開發的夥伴們。下次見。