iT邦幫忙

2025 iThome 鐵人賽

DAY 14
1
Cloud Native

《30 天 Cloud Native:AI 行程規劃後端開發》系列 第 14

Day14 - 從 ADK 到 Cloud Run:打造完整的 Vertex AI Agent 呼叫流程

  • 分享至 

  • xImage
  •  

部屬遠端 Agent 的類別差異與錯誤排查

找到問題了!重新部屬範例程式後成功運行遠端 Agent,發現差異在於 Agent 的類別:

  • 範例 multi_tool_agent 部屬時的類別是 google.adk.agents.Agent
  • 昨天寫的 trip_agent 部屬時的類別是 vertexai.preview.reasoning_engines.AdkApp

從程式碼來看,差異在於部屬時使用的參數:

# multi_tool_agent 
remote_agent = agent_engines.create(
	agent_engine=Agent(...),
	...
)

# AdkApp
remote_agent = agent_engines.create(
	agent_engine=AdkApp(agent=Agent(...)),
	...
)

也就是多包了一層,而錯誤訊息顯示:

  Input should be a valid dictionary or instance of BaseAgent [type=model_type, input_value=<vertexai.preview.reasoni...bject at 0x7f77a61289d0>, input_type=AdkApp]

其實就是在說執行時應該要使用 BaseAgent 的實例或是 Dictionary。但這算是 Bug 嗎?部屬時沒事,執行時卻出問題且沒有噴錯訊息,要進 Logs Explorer 才能看到。

我會使用 AdkApp 部屬的原因是 Agent Development Kit 文件中部屬前的 app 變數是 AdkApp

https://ithelp.ithome.com.tw/upload/images/20250828/20178194rRGt56bkPk.png

後面部屬時用的就是 app 變數:

https://ithelp.ithome.com.tw/upload/images/20250828/20178194qF84lTYJFB.png

Quickstart: Develop and deploy agents on Vertex AI Agent Engine 文件內也是使用 AdkApp 來部屬:

https://ithelp.ithome.com.tw/upload/images/20250828/20178194mhF5hACnV3.png

所以想跟我一樣用 ADK 建立 Vertex AI Agent Engine 的要注意一下。

建立 Cloud Run API Server 並處理驗證與錯誤

接下來請 LLM 幫我產個 Cloud Run 專案用來架設 API server,當 API 收到以下的請求格式時呼叫 Agent Engine:

{"locations": ["Tokyo"], "startDate": "2025-09-10", "days": 2, "language": "Chinese Traditional"}

將產好的專案部屬到 Cloud Run 不意外地遇到錯誤:

https://ithelp.ithome.com.tw/upload/images/20250828/20178194rotyglpY3d.png

看起來是 remote_agent.async_stream_query 呼叫時出錯,為了方便 Debug 先弄個本地版本:

docker run --env-file .dockerenv -p 8098:8080 -it apiserver

結果又遇到其他錯誤:

  File "/usr/local/lib/python3.10/site-packages/google/cloud/aiplatform/initializer.py", line 119, in _set_project_as_env_var_or_google_auth_default
    credentials, _ = google.auth.default(scopes=constants.DEFAULT_AUTHED_SCOPES)
  File "/usr/local/lib/python3.10/site-packages/google/auth/_default.py", line 685, in default
    raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.

看起來是沒有設定 Google Cloud 的驗證權限導致。查了一下,如果部屬在 Google Cloud 上就不用擔心這個,但要在本地 Docker 跑的話要把 application_default_credentials.json 放進去,所以先將檔案 mount 進 /tmp/adc.json

docker run --env-file .dockerenv -e PORT=8080 -p 8098:8080 -v ~/.config/gcloud/application_default_credentials.json:/tmp/adc.json -it apiserver

然後 .dockerenv 裡面要多設定變數指向 /tmp/adc.json

GOOGLE_APPLICATION_CREDENTIALS=/tmp/adc.json

另外補充一下,為了使用環境變數控制部屬在容器內的 Port ,在 Dockerfile 要這樣寫:

CMD ["sh", "-c", "uvicorn main:api --host 0.0.0.0 --port $PORT"]

不能這樣寫:

CMD ["uvicorn", "main:api", "--host", "0.0.0.0", "--port", "$PORT"]

因為沒用 sh 包起來的話,等同於直接把 $PORT 字串當作參數餵給 uvicorn。要使用 sh -c 包起來 $PORT 變數才會被 sh 解析然後餵給 uvicorn。可以參考 docker - Using ENV var in CMD in the Dockerfile - Stack Overflow

修正 Agent 回傳格式與 Pydantic 錯誤

解決了環境問題後回到呼叫 API 的部分,剛剛的 remote_agent.async_stream_query 問題只是少給了 user_id 參數。設定好後又遇到 JSON 解析錯誤,原因是 Agent 回傳 childActivity: [] 而 Pydantic 沒有處理。

為了讓 childActivity 可以接受空陣列,要這樣定義:

    childActivities: List[ChildActivity] = Field(default_factory=list)

另外還要允許 transportTypenull,之後就成功了!

https://ithelp.ithome.com.tw/upload/images/20250828/20178194l0flgmIRPs.png


上一篇
Day13 - 從 Prompt 到 JSON:Gemini API 行程規劃實作與錯誤排查全紀錄
下一篇
Day15 - 我的 Cloud Native 架構,真的會自動擴展嗎?一場壓力測試的告白
系列文
《30 天 Cloud Native:AI 行程規劃後端開發》20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言