This Post is under 軟體開發
在前文使用 PHP 呼叫 Google Gemini API 生成內容,是以模型既有的知識來回答。而模型既有的知識受限於訓練所餵給的資料。即使是最新的模型,其知識內容涵蓋的範圍大概會落後現在年代一、兩年以上。譬如現在是2025年,若你問 gemini-2.5-flash-preview-04-17 模型(2025-04-17),Gemini會回答:「現任美國總統是 **喬·拜登(Joe Biden)**。他是民主黨的成員。」顯然這不符合現實,因此生成式AI工具都發展出從網路抓取即時資訊來統整再回答,這就是所謂的「以 Google 搜尋建立基準(Grounding with Google Search)」,這樣生成式AI的回答就會比較即使與準備。
不過有些模型需要是付費帳戶才能使用基於Google搜尋的回應功能,且可能會有使用次數的限制。目前試過gemini-2.0-flash,現在還可以免費帳戶使用這項功能。你可以在底下的範例中,改變不同的模型,看看各個模型對這項功能的支援情形,或是驗證Gemini的回答是否能讓你滿意。於是在”基於Google搜尋”勾選的狀態在問一次gemini-2.0-flash,答案會變成:「根據目前時間(2025年5月12日),美國現任總統是唐納·川普。 他於2025年1月20日宣誓就職。」
以下是在網站伺服器端呼叫 Google Gemini 基於Google搜尋生成內容的程式碼,以 php curl 來實作,參考:Grounding with Google Search,新增的程式碼以粗體字表示。根據文件, Google 搜尋擷取功能(google_search_retrieval)僅支援 Gemini 1.5 模型。在 Gemini 2.0 模型,應將搜尋功能(google_search)視為工具。因此以下根據模型版本的不同來設定tools。
值得一提的是,在 Gemini 1.5 模型設定 google_search_retrieval參數或是在 Gemini 2.0 模型設定 google_search參數時,就算沒有參數也不能省略(除了dynamic_threshold有預設值0.3,可省略不給),否則會出現類似「 Unknown name google_search_retrieval at tools」的錯誤訊息,但是google_search其實是沒有參數的,如果傳進空的陣列或是null都不是正確的做法。試了好久,原來是要將空陣列先轉成 object 型態,這樣在 json_encode就會將之變成符合rest api文件的寫法 “google_search”: {} 了。
<?php $model = isset($_REQUEST['m']) ? $_REQUEST['m'] : ""; $geminiQuery = isset($_REQUEST['q']) ? $_REQUEST['q'] : ""; $grounding = isset($_REQUEST['grounding']); $api_key = "YOUR_GEMINI_KEY"; $url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$api_key}"; $data = array( "contents" => array( array( "role" => "user", "parts" => array( array( "text" => $geminiQuery ) ) ) ) ); if($grounding) { $modelParts = explode("-", $model); $data["tools"] = ($modelParts[1]) == "1.5" ? array( "google_search_retrieval" => array( "dynamic_retrieval_config" => array( "mode"=> "MODE_DYNAMIC", // "dynamic_threshold"=> 0.3 ) ) ) : array( "google_search" => (object)[] ); } $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); curl_close($ch); header('Content-type: application/json'); if (curl_errno($ch)) { die("{ 'error': '" . curl_error($ch) . "'}"); } echo $response;