GoにおけるGemini APIでの検索グラウンディングの活用
はじめに
こんにちは!サロンスタッフ予約サービス「minimo」でAI推進チームに所属している洗川です。
近年はLLM(大規模言語モデル)の進化が目覚ましく、多くのサービスで活用されています。しかし、LLMには「学習データに含まれない最新の情報は知らない」「事実に基づかない内容を生成することがある(ハルシネーション)」といった課題もあります。
今回ご紹介するGemini APIの検索グラウンディングは、これらの課題に対する非常に強力な機能です。Google検索の結果をリアルタイムに参照し、回答の精度と鮮度を向上させることができます。
本記事では、この検索グラウンディング機能をGoで実装する方法と、その際に少し工夫が必要な「出典URLの取り扱い」について解説します。
Gemini APIの検索グラウンディングとは?
検索グラウンディング(Grounding with Google Search)は、Geminiがユーザーからの質問に答える際に、Google検索の結果をリアルタイムに参照する機能です。
これにより、以下のようなメリットがあります。
- 最新情報の取得: モデルの学習データに含まれていない、最新のニュースや出来事に関する質問にも答えられるようになる
- ハルシネーションの抑制: 回答がWeb上の情報に基づいているため、より正確で信頼性の高い回答が期待できる
-
出典の明記: 回答の根拠となったWebページのURLを提示してくれるため、ユーザーは情報の真偽を自分で確認できる
例えば、「最近発表されたオリンピックの情報は?」のような、特定の時点での最新情報が必要な質問に対して、非常に有効です。
Goでの実装方法
それでは早速、Goで検索グラウンディングを実装する方法を見ていきましょう。公式のGoライブラリ (google.golang.org/genai
) を使うと、簡単に実装できます。
実装コード
以下が、検索グラウンディングを有効にしてGemini APIを呼び出すサンプルコードです。
package main
import (
"context"
"fmt"
"log"
"os"
"google.golang.org/api/option"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, &genai.ClientConfig{
Project: "your-project",
Location: "some-gcp-location",
Backend: genai.BackendVertexAI,
})
if err != nil {
log.Fatalf("NewClientに失敗しました: %v", err)
}
defer client.Close()
model := client.GenerativeModel("gemini-2.5-flash")
// --- 検索グラウンディングを有効にする ---
model.Tools = []*genai.Tool{
{GoogleSearch: &genai.GoogleSearch{}},
}
// 必要に応じてモデルの振る舞いを指示
model.SystemInstruction = &genai.Content{
Parts: []genai.Part{
genai.Text("あなたは礼儀正しい日本語アシスタントです。50文字以内で答えてください。"),
},
}
// ユーザーからの質問
prompt := genai.Text("最近発表されたオリンピックの情報は?出典もほしい")
// --- API呼び出し ---
resp, err := model.GenerateContent(ctx, prompt)
if err != nil {
log.Fatalf("GenerateContentに失敗しました: %v", err)
}
// レスポンスのテキスト部分を出力
for _, part := range resp.Candidates[0].Content.Parts {
if txt, ok := part.(genai.Text); ok {
fmt.Println(txt)
}
}
// レスポンスのメタデータから出典情報を取得
if resp.Candidates[0].GroundingMetadata != nil {
fmt.Println("\n--- 出典 ---")
for _, citation := range resp.Candidates[0].GroundingMetadata.Citations {
fmt.Printf("URI: %s\n", citation.URI)
fmt.Printf("Title: %s\n", citation.Title)
}
}
}
※ Vertex AIモデルを利用するため、GCPプロジェクトの設定などが必要です。今回は gemini-2.5-flash
を利用する例にしています。
コードのポイント
実装のポイントは、model.Tools
に &genai.Tool{GoogleSearch: &genai.GoogleSearch{}}
を設定する箇所です。これにより、Geminiは質問の内容に応じて自動的にGoogle検索を行い、その結果を考慮して回答を生成してくれます。
APIのレスポンスには、生成されたテキストだけでなく、GroundingMetadata
が含まれており、ここから出典元のURLやタイトルを取得できます。
出典URLのリダイレクトを解決する
検索グラウンディングで取得できる出典URLですが、一つ注意点があります。返却されるURLは、https://vertextaisearch.google.com/...
のような、Googleの検索結果を指す一時的なURLになっているようです。
このURLは、最終的な出典元のページにリダイレクトされるようになっています。そのため、ユーザーに提示する前に、このリダイレクトを解決して最終的なURLを取得する必要があります。
リダイレクト解決コード
Goの標準ライブラリ net/http
を使うことで、リダイレクト先のURLを簡単に取得できます。
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
)
// 与えられたURLを元に最終的なURLを返す
func resolveFinalURL(ctx context.Context, url string) (string, error) {
// リクエストのタイムアウトを設定
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", fmt.Errorf("NewRequestWithContextに失敗しました: %w", err)
}
// User-Agentは適当なものを指定
req.Header.Set("User-Agent", "resolve-client")
// 転送量を最小化するための対応
req.Header.Set("Range", "bytes=0-0")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("DefaultClient.Doに失敗しました: %w", err)
}
defer resp.Body.Close()
// レスポンスオブジェクトのRequestフィールドには、最終的なリクエスト情報が格納されている
return resp.Request.URL.String(), nil
}
func main() {
// Gemini APIから返されるURLの例(ダミー)
// 実際にはAPIのレスポンスからこのURLを取得する
originalURL := "http://example.com/redirect"
fmt.Printf("元のURL: %s\n", originalURL)
finalURL, err := resolveFinalURL(context.Background(), originalURL)
if err != nil {
log.Fatalf("resolveFinalURLに失敗しました: %v", err)
}
fmt.Printf("解決後のURL: %s\n", finalURL)
}
コードのポイント
Goの http.DefaultClient
は、デフォルトでリダイレクトを自動的に追跡してくれるため、特別な設定は不要です。http.Client.Do()
を実行した後のレスポンス resp
に含まれる resp.Request.URL
を見るだけで、リダイレクト後の最終的なURLを取得できます。
また、Range
ヘッダーを指定することで、転送量を最小化しています。
この一手間を加えることで、ユーザーが直接アクセスできる正しい出典情報を提供できます。
まとめ
本記事では、Gemini APIの検索グラウンディング機能をGoで実装する方法と、その際の出典URLの扱い方について解説しました。
- 検索グラウンディングは、
Tools
にGoogleSearch
を追加すれば有効化できる - 最新情報に基づいた、信頼性の高い回答を生成するのに非常に役立つ
- 出典URLはリダイレクトされるため、
net/http
を使って最終的なURLを取得する必要がある
本記事が、Gemini APIの活用を検討している方の参考になれば幸いです。
最後に
minimoでは、サービス開発に一緒に挑戦してくれる仲間を募集しています!ご興味のある方は、ぜひ採用ページをご覧ください。
Discussion