Tool use with Live API

การใช้เครื่องมือช่วยให้ Live API ทำได้มากกว่าแค่การสนทนา โดยช่วยให้ API สามารถ ดำเนินการในโลกแห่งความเป็นจริงและดึงบริบทภายนอกเข้ามาได้ในขณะที่ยังคง การเชื่อมต่อแบบเรียลไทม์ คุณกำหนดเครื่องมือต่างๆ เช่น การเรียกใช้ฟังก์ชัน และ Google Search ได้ด้วย Live API

ภาพรวมของเครื่องมือที่รองรับ

ต่อไปนี้เป็นภาพรวมโดยย่อของเครื่องมือที่ใช้ได้สำหรับโมเดล Live API

เครื่องมือ gemini-2.5-flash-native-audio-preview-09-2025
ค้นหา ใช่
การเรียกใช้ฟังก์ชัน ใช่
Google Maps ไม่
การรันโค้ด ไม่
บริบทของ URL ไม่

การเรียกใช้ฟังก์ชัน

Live API รองรับการเรียกใช้ฟังก์ชันเช่นเดียวกับคำขอการสร้างเนื้อหาปกติ การเรียกใช้ฟังก์ชันช่วยให้ Live API โต้ตอบกับข้อมูลและโปรแกรมภายนอกได้ ซึ่งจะช่วยเพิ่มสิ่งที่แอปพลิเคชันของคุณทำได้เป็นอย่างมาก

คุณสามารถกำหนดการประกาศฟังก์ชันเป็นส่วนหนึ่งของการกำหนดค่าเซสชันได้ หลังจากได้รับฟังก์ชันคอลแล้ว ไคลเอ็นต์ควรตอบกลับด้วยรายการออบเจ็กต์ FunctionResponseโดยใช้เมธอด session.send_tool_response

ดูข้อมูลเพิ่มเติมได้ที่บทแนะนำการเรียกใช้ฟังก์ชัน

Python

import asyncio
import wave
from google import genai
from google.genai import types

client = genai.Client()

model = "gemini-2.5-flash-native-audio-preview-09-2025"

# Simple function definitions
turn_on_the_lights = {"name": "turn_on_the_lights"}
turn_off_the_lights = {"name": "turn_off_the_lights"}

tools = [{"function_declarations": [turn_on_the_lights, turn_off_the_lights]}]
config = {"response_modalities": ["AUDIO"], "tools": tools}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        prompt = "Turn on the lights please"
        await session.send_client_content(turns={"parts": [{"text": prompt}]})

        wf = wave.open("audio.wav", "wb")
        wf.setnchannels(1)
        wf.setsampwidth(2)
        wf.setframerate(24000)  # Output is 24kHz

        async for response in session.receive():
            if response.data is not None:
                wf.writeframes(response.data)
            elif response.tool_call:
                print("The tool was called")
                function_responses = []
                for fc in response.tool_call.function_calls:
                    function_response = types.FunctionResponse(
                        id=fc.id,
                        name=fc.name,
                        response={ "result": "ok" } # simple, hard-coded function response
                    )
                    function_responses.append(function_response)

                await session.send_tool_response(function_responses=function_responses)

        wf.close()

if __name__ == "__main__":
    asyncio.run(main())

JavaScript

import { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";
import pkg from 'wavefile';  // npm install wavefile
const { WaveFile } = pkg;

const ai = new GoogleGenAI({});
const model = 'gemini-2.5-flash-native-audio-preview-09-2025';

// Simple function definitions
const turn_on_the_lights = { name: "turn_on_the_lights" } // , description: '...', parameters: { ... }
const turn_off_the_lights = { name: "turn_off_the_lights" }

const tools = [{ functionDeclarations: [turn_on_the_lights, turn_off_the_lights] }]

const config = {
  responseModalities: [Modality.AUDIO],
  tools: tools
}

async function live() {
  const responseQueue = [];

  async function waitMessage() {
    let done = false;
    let message = undefined;
    while (!done) {
      message = responseQueue.shift();
      if (message) {
        done = true;
      } else {
        await new Promise((resolve) => setTimeout(resolve, 100));
      }
    }
    return message;
  }

  async function handleTurn() {
    const turns = [];
    let done = false;
    while (!done) {
      const message = await waitMessage();
      turns.push(message);
      if (message.serverContent && message.serverContent.turnComplete) {
        done = true;
      } else if (message.toolCall) {
        done = true;
      }
    }
    return turns;
  }

  const session = await ai.live.connect({
    model: model,
    callbacks: {
      onopen: function () {
        console.debug('Opened');
      },
      onmessage: function (message) {
        responseQueue.push(message);
      },
      onerror: function (e) {
        console.debug('Error:', e.message);
      },
      onclose: function (e) {
        console.debug('Close:', e.reason);
      },
    },
    config: config,
  });

  const inputTurns = 'Turn on the lights please';
  session.sendClientContent({ turns: inputTurns });

  let turns = await handleTurn();

  for (const turn of turns) {
    if (turn.toolCall) {
      console.debug('A tool was called');
      const functionResponses = [];
      for (const fc of turn.toolCall.functionCalls) {
        functionResponses.push({
          id: fc.id,
          name: fc.name,
          response: { result: "ok" } // simple, hard-coded function response
        });
      }

      console.debug('Sending tool response...\n');
      session.sendToolResponse({ functionResponses: functionResponses });
    }
  }

  // Check again for new messages
  turns = await handleTurn();

  // Combine audio data strings and save as wave file
  const combinedAudio = turns.reduce((acc, turn) => {
      if (turn.data) {
          const buffer = Buffer.from(turn.data, 'base64');
          const intArray = new Int16Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Int16Array.BYTES_PER_ELEMENT);
          return acc.concat(Array.from(intArray));
      }
      return acc;
  }, []);

  const audioBuffer = new Int16Array(combinedAudio);

  const wf = new WaveFile();
  wf.fromScratch(1, 24000, '16', audioBuffer);  // output is 24kHz
  fs.writeFileSync('audio.wav', wf.toBuffer());

  session.close();
}

async function main() {
  await live().catch((e) => console.error('got error', e));
}

main();

โมเดลสามารถสร้างการเรียกใช้ฟังก์ชันหลายรายการและโค้ดที่จำเป็นต่อการเชื่อมโยงเอาต์พุตจากพรอมต์เดียว โค้ดนี้จะทำงานในสภาพแวดล้อมแซนด์บ็อกซ์ เพื่อสร้างข้อความ BidiGenerateContentToolCall ที่ตามมา

การเรียกใช้ฟังก์ชันแบบอะซิงโครนัส

การเรียกใช้ฟังก์ชันจะดำเนินการตามลำดับโดยค่าเริ่มต้น ซึ่งหมายความว่าการดำเนินการจะหยุดชั่วคราว จนกว่าผลลัพธ์ของการเรียกใช้ฟังก์ชันแต่ละรายการจะพร้อมใช้งาน ซึ่งจะช่วยให้ประมวลผลตามลำดับได้ ซึ่งหมายความว่าคุณจะโต้ตอบกับโมเดลต่อไปไม่ได้ในขณะที่ฟังก์ชันกำลังทำงาน

หากไม่ต้องการบล็อกการสนทนา คุณสามารถบอกโมเดลให้เรียกใช้ฟังก์ชันแบบไม่พร้อมกันได้ โดยคุณต้องเพิ่ม behavior ใน คำจำกัดความฟังก์ชันก่อน

Python

# Non-blocking function definitions
turn_on_the_lights = {"name": "turn_on_the_lights", "behavior": "NON_BLOCKING"} # turn_on_the_lights will run asynchronously
turn_off_the_lights = {"name": "turn_off_the_lights"} # turn_off_the_lights will still pause all interactions with the model

JavaScript

import { GoogleGenAI, Modality, Behavior } from '@google/genai';

// Non-blocking function definitions
const turn_on_the_lights = {name: "turn_on_the_lights", behavior: Behavior.NON_BLOCKING}

// Blocking function definitions
const turn_off_the_lights = {name: "turn_off_the_lights"}

const tools = [{ functionDeclarations: [turn_on_the_lights, turn_off_the_lights] }]

NON-BLOCKING ช่วยให้ฟังก์ชันทำงานแบบไม่พร้อมกันในขณะที่คุณโต้ตอบกับโมเดลต่อไปได้

จากนั้นคุณต้องบอกโมเดลว่าควรทำงานอย่างไรเมื่อได้รับ FunctionResponse โดยใช้พารามิเตอร์ scheduling โดยอาจเป็นอย่างใดอย่างหนึ่งต่อไปนี้

  • ขัดจังหวะสิ่งที่กำลังทำอยู่และแจ้งให้คุณทราบเกี่ยวกับคำตอบที่ได้รับทันที (scheduling="INTERRUPT")
  • รอจนกว่าจะเสร็จสิ้นกับสิ่งที่กำลังทำอยู่ (scheduling="WHEN_IDLE")
  • หรือจะปล่อยไว้และใช้ความรู้นั้นในการสนทนาในภายหลังก็ได้ (scheduling="SILENT")

Python

# for a non-blocking function definition, apply scheduling in the function response:
  function_response = types.FunctionResponse(
      id=fc.id,
      name=fc.name,
      response={
          "result": "ok",
          "scheduling": "INTERRUPT" # Can also be WHEN_IDLE or SILENT
      }
  )

JavaScript

import { GoogleGenAI, Modality, Behavior, FunctionResponseScheduling } from '@google/genai';

// for a non-blocking function definition, apply scheduling in the function response:
const functionResponse = {
  id: fc.id,
  name: fc.name,
  response: {
    result: "ok",
    scheduling: FunctionResponseScheduling.INTERRUPT  // Can also be WHEN_IDLE or SILENT
  }
}

คุณเปิดใช้การอ้างอิงจาก Google Search ได้โดยเป็นส่วนหนึ่งของการกำหนดค่าเซสชัน ซึ่งจะช่วยเพิ่มความแม่นยำของ Live API และป้องกัน การแต่งเรื่อง ดูข้อมูลเพิ่มเติมได้ที่บทแนะนำการกราวด์

Python

import asyncio
import wave
from google import genai
from google.genai import types

client = genai.Client()

model = "gemini-2.5-flash-native-audio-preview-09-2025"

tools = [{'google_search': {}}]
config = {"response_modalities": ["AUDIO"], "tools": tools}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        prompt = "When did the last Brazil vs. Argentina soccer match happen?"
        await session.send_client_content(turns={"parts": [{"text": prompt}]})

        wf = wave.open("audio.wav", "wb")
        wf.setnchannels(1)
        wf.setsampwidth(2)
        wf.setframerate(24000)  # Output is 24kHz

        async for chunk in session.receive():
            if chunk.server_content:
                if chunk.data is not None:
                    wf.writeframes(chunk.data)

                # The model might generate and execute Python code to use Search
                model_turn = chunk.server_content.model_turn
                if model_turn:
                    for part in model_turn.parts:
                        if part.executable_code is not None:
                            print(part.executable_code.code)

                        if part.code_execution_result is not None:
                            print(part.code_execution_result.output)

        wf.close()

if __name__ == "__main__":
    asyncio.run(main())

JavaScript

import { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";
import pkg from 'wavefile';  // npm install wavefile
const { WaveFile } = pkg;

const ai = new GoogleGenAI({});
const model = 'gemini-2.5-flash-native-audio-preview-09-2025';

const tools = [{ googleSearch: {} }]
const config = {
  responseModalities: [Modality.AUDIO],
  tools: tools
}

async function live() {
  const responseQueue = [];

  async function waitMessage() {
    let done = false;
    let message = undefined;
    while (!done) {
      message = responseQueue.shift();
      if (message) {
        done = true;
      } else {
        await new Promise((resolve) => setTimeout(resolve, 100));
      }
    }
    return message;
  }

  async function handleTurn() {
    const turns = [];
    let done = false;
    while (!done) {
      const message = await waitMessage();
      turns.push(message);
      if (message.serverContent && message.serverContent.turnComplete) {
        done = true;
      } else if (message.toolCall) {
        done = true;
      }
    }
    return turns;
  }

  const session = await ai.live.connect({
    model: model,
    callbacks: {
      onopen: function () {
        console.debug('Opened');
      },
      onmessage: function (message) {
        responseQueue.push(message);
      },
      onerror: function (e) {
        console.debug('Error:', e.message);
      },
      onclose: function (e) {
        console.debug('Close:', e.reason);
      },
    },
    config: config,
  });

  const inputTurns = 'When did the last Brazil vs. Argentina soccer match happen?';
  session.sendClientContent({ turns: inputTurns });

  let turns = await handleTurn();

  let combinedData = '';
  for (const turn of turns) {
    if (turn.serverContent && turn.serverContent.modelTurn && turn.serverContent.modelTurn.parts) {
      for (const part of turn.serverContent.modelTurn.parts) {
        if (part.executableCode) {
          console.debug('executableCode: %s\n', part.executableCode.code);
        }
        else if (part.codeExecutionResult) {
          console.debug('codeExecutionResult: %s\n', part.codeExecutionResult.output);
        }
        else if (part.inlineData && typeof part.inlineData.data === 'string') {
          combinedData += atob(part.inlineData.data);
        }
      }
    }
  }

  // Convert the base64-encoded string of bytes into a Buffer.
  const buffer = Buffer.from(combinedData, 'binary');

  // The buffer contains raw bytes. For 16-bit audio, we need to interpret every 2 bytes as a single sample.
  const intArray = new Int16Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Int16Array.BYTES_PER_ELEMENT);

  const wf = new WaveFile();
  // The API returns 16-bit PCM audio at a 24kHz sample rate.
  wf.fromScratch(1, 24000, '16', intArray);
  fs.writeFileSync('audio.wav', wf.toBuffer());

  session.close();
}

async function main() {
  await live().catch((e) => console.error('got error', e));
}

main();

การรวมเครื่องมือหลายอย่าง

คุณสามารถรวมเครื่องมือหลายอย่างภายใน Live API เพื่อเพิ่มความสามารถของแอปพลิเคชันให้มากยิ่งขึ้นได้ ดังนี้

Python

prompt = """
Hey, I need you to do two things for me.

1. Use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024?
2. Then turn on the lights

Thanks!
"""

tools = [
    {"google_search": {}},
    {"function_declarations": [turn_on_the_lights, turn_off_the_lights]},
]

config = {"response_modalities": ["AUDIO"], "tools": tools}

# ... remaining model call

JavaScript

const prompt = `Hey, I need you to do two things for me.

1. Use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024?
2. Then turn on the lights

Thanks!
`

const tools = [
  { googleSearch: {} },
  { functionDeclarations: [turn_on_the_lights, turn_off_the_lights] }
]

const config = {
  responseModalities: [Modality.AUDIO],
  tools: tools
}

// ... remaining model call

ขั้นตอนถัดไป