Gemini 2.0 Multimodal Live APIで遊ぼう


Created by Masayuki Shimizu / @_shimizu

自己紹介



  • 清水正行
  • 群馬県高崎市在住
  • 日経→フリーランス
  • DataViz / GIS エンジニア
  • 資産運用

日経:Visual Data

はじめに

Gemniniとは?


Googleが開発・提供している生成AIモデル。 文章の生成や要約、画像の編集、翻訳、ソースコードの生成など、さまざまなタスクに対応できる。
ChatGPTやClaudeに要らべていまいち存在感が薄い(気がする)
と思ったけど直前でバズってた。

マルチモーダルとは?


テキストだけでなく、画像、動画、音声などをAIへの入力として扱える

ライブとは?


AIへの入力をリアルタイムで行える。一般的なターン制のやりとりに比べてより自然な会話を行うことができる。 また、AIが返答中であっても割り込んで入力をおこなことができる

ためしてみよう


Google AI Stdio

Gemini のモデルをテストできる実験環境。APIキーの発行などもこのサービスから行える。「Stream Realtime」のタブからMultimodal Live APIのテストが行える

Multimodal Live APIを使う

APIを使うと?


自身のアプリケーションやサービスの中に、リアルタイムで応答するAIを組み込むことができる


  • 画面を一緒に見ながらアプリの操作方法を教えてくれるAI
  • 音声でリアルタイムに会話しながら注文を受けるAI

  • とか作れそう

    注意点


    Multimodal Live APIを活用するにはWebSocketsを使う必要があります。ストリーミング処理になれていないと構築が難しいです。

    スターターキットを使おう


    multimodal-live-api-web-console

    Googleが公式で公開しているMultimodal Live APIを使用するためのReactベースのスターターキット。ストリーミング処理やオーディオ、マイク、webカメラ、画面キャプチャなどのメディア処理などが最初からう用意されている

    ためしてみよう


    スターターキットのデモ

    スターターキットの解説

    使い方


    multimodal-live-api-web-console

  • ダウンロード
  • npm install
  • .envにAPIキーを記載
  • npm start
  • 別ブランチに別のスターターキットが入ってます。

    ファイル構成(src以下)

    src
    ├── App.scss
    ├── App.test.tsx
    ├── App.tsx
    ├── components
    │   ├── altair
    │   │   └── Altair.tsx
    │   ├── audio-pulse
    │   │   ├── AudioPulse.tsx
    │   │   └── audio-pulse.scss
    │   ├── control-tray
    │   │   ├── ControlTray.tsx
    │   │   └── control-tray.scss
    │   ├── logger
    │   │   ├── Logger.tsx
    │   │   ├── logger.scss
    │   │   └── mock-logs.ts
    │   └── side-panel
    │   ├── SidePanel.tsx
    │   └── side-panel.scss
    ├── contexts
    │   └── LiveAPIContext.tsx
    ├── hooks
    │   ├── use-live-api.ts
    │   ├── use-media-stream-mux.ts
    │   ├── use-screen-capture.ts
    │   └── use-webcam.ts
    ├── index.css
    ├── index.tsx
    ├── lib
    │   ├── audio-recorder.ts
    │   ├── audio-streamer.ts
    │   ├── audioworklet-registry.ts
    │   ├── multimodal-live-client.ts
    │   ├── store-logger.ts
    │   ├── utils.ts
    │   └── worklets
    │   ├── audio-processing.ts
    │   └── vol-meter.ts
    ├── multimodal-live-types.ts
    ├── react-app-env.d.ts
    ├── reportWebVitals.ts
    └── setupTests.ts
    
    			

    最も重要なファイル


    スターターキットとしてはコード量が多いが、殆どは通信周りの処理で複雑になっているだけ。とりあえず一番最初に理解すべきは以下のコード。

    src
    			├── components
    			│   ├── altair
    			│   │   └── Altair.tsx  *
    			

    Altair.tsxで何をやっているか


    Geminiに「render_altair」というファンクションコーリングを登録し、AIの判断で関数呼び出しを行わせVega-Altairとういうチャートライブラリを用いてチャートを出力している

    ファンクションコーリングとは


    自然言語のプロンプトを使って、AIモデルがユーザーの意図を理解し、外部関数の呼び出し(APIやアプリ内ロジックなど)を提案・実行する仕組み。

    つまり、AIが自ら判断してイベントを発火しプログラム(関数)を実行する。

    ファンクションコーリングの構成


    関数定義

  • OpenAPI / JSON Schema形式で、関数名、引数、型、説明を定義
  • モデル設定

  • 使用モデルの設定
  • 入出力の設定(テキストor音声など)
  • 定義した関数をtoolsに登録
  • 関数が呼ばれたときのハンドリング

  • AIからイベントが発火したさいのハンドリング処理を設定
  • 関数定義


    // Altairグラフを描画するための関数宣言オブジェクト
    const declaration: FunctionDeclaration = {
    	// 関数の名前
    	name: "render_altair",
    
    	// 関数の説明
    	description: "Displays an altair graph in json format.", //altair グラフを json フォーマットで表示します。
    
    	// パラメータの定義
    	parameters: {
    		// パラメータはオブジェクト型で定義される
    		type: SchemaType.OBJECT,
    
    		// プロパティの定義
    		properties: {
    			json_graph: { //関数呼び出しの際に引数として渡される
    				type: SchemaType.STRING, // 文字列型のデータを受け取る
    				description:
    					"JSON STRING representation of the graph to render. Must be a string, not a json object", // プロンプト「レンダリングするグラフのJSON文字列表現。 json オブジェクトではなく、文字列でなければなりません。」
    			},
    		},
    
    		// 必須パラメータの指定
    		required: ["json_graph"],
    	},
    };
    

    モデル設定


    useEffect(() => {
    	// Geminiのリクエスト設定を行うカスタムフック
    	setConfig({
    		// 使用するAIモデルのバージョン
    		model: "models/gemini-2.0-flash-exp",
    
    		// 音声出力の設定
    		generationConfig: {
    			responseModalities: "audio", // AIのレスポンスとして音声を使用
    			speechConfig: {
    				voiceConfig: { prebuiltVoiceConfig: { voiceName: "Aoede" } }, // 音声の種類を "Aoede" に設定
    			},
    		},
    
    		// システム命令の設定 (AIがどのように振る舞うか)
    		systemInstruction: {
    			parts: [
    				{
    				//プロンプト「あなたはアシスタントだ。 私がグラフの作成を依頼するときはいつでも、私が用意した「render_altair」関数を呼び出してください。 追加情報は求めず、最善の判断をしてください。」
    				text: 'You are my helpful assistant. Any time I ask you for a graph call the "render_altair" function I have provided you. Dont ask for additional information just make your best judgement.',
    				},
    			],
    		},
    
    		// 利用可能なツール (AIが実行できる追加機能)
    		tools: [
    			{ googleSearch: {} }, // 公式が用意しているファンクションコーリング(Google検索を利用できるようにする)
    			{ functionDeclarations: [declaration] }, // "render_altair" 関数をAIに登録
    		],
    	});
    }, [setConfig]);
    		

    関数呼び出し時のハンドリング


    useEffect(() => {
    	// AI からのツール呼び出しを処理するハンドラ
    	const onToolCall = (toolCall: ToolCall) => {
    
    		// toolCall に含まれる関数呼び出しの中から "render_altair" に一致するものを探す
    		const fc = toolCall.functionCalls.find(
    			(fc) => fc.name === declaration.name,
    		);
    
    		// "render_altair" 関数が見つかった場合、引数として渡された JSON グラフを取得し、ステートを更新
    		if (fc) {
    			const str = (fc.args as any).json_graph; // 引数として渡された JSON グラフを取得
    			setJSONString(str); // チャートデータのステートを更新
    		}
    
    		// ツールの呼び出しに応答を返す処理
    		// この場合、ツールの処理が成功したことを AI に伝える
    		if (toolCall.functionCalls.length) {
    		setTimeout(
    			() =>
    			client.sendToolResponse({
    				functionResponses: toolCall.functionCalls.map((fc) => ({
    					response: { output: { success: true } }, // 成功したことを示すレスポンス
    					id: fc.id, // 各関数呼び出しの ID を返す
    				})),
    			}),
    			200, // 200ms の遅延を入れる
    		);
    		}
    	};
    
    	// "toolcall" イベントをリスニングしハンドラを登録する
    	client.on("toolcall", onToolCall);
    
    	// クリーンアップ処理: コンポーネントのアンマウント時にイベントリスナーを解除
    	return () => {
    		client.off("toolcall", onToolCall);
    	};
    }, [client]); //LiveAPIContextで取得されたAPIクライアント
    			
    		

    Next Step


    まずは、スターターキットにオリジナルのファクションコーリングを追加して機能を増やしていくのが良さそう。

    最後に

    まだまだなところ


  • 日本語の音声は認識精度やアクセントがいまいち
  • 「AIが独自の判断で関数を呼ぶ」という処理を書くのに慣れない
  • Gemini 2.0 多機能過ぎて使いこなせない
  • でも、最高に楽しくて未来を感じれるのでGeminiお勧めです!