Lección 21 · 10 min · Gratis

Primeros pasos con las herramientas de la API en vivo

Copyright 2026 Google LLC.
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Este notebook proporciona ejemplos de cómo usar herramientas con la API multimodal en vivo con Gemini 2.5.

La API proporciona herramientas de Google Search, Code Execution y Function Calling. Los modelos Gemini anteriores admitían versiones de estas herramientas. El cambio más grande con Gemini 2.5 (en la API en vivo) es que, básicamente, todas las herramientas son manejadas por Code Execution. Con ese cambio, puedes usar múltiples herramientas en una sola llamada a la API, y el modelo puede usar múltiples herramientas en un solo bloque de ejecución de código.

Este tutorial asume que estás familiarizado con la API en vivo, como se describe en este tutorial.

Configuración

Instalar el SDK

El nuevo SDK de Google Gen AI proporciona acceso programático a Gemini 2.5 (y modelos anteriores) usando las API de Google AI para desarrolladores y Vertex AI. Con algunas excepciones, el código que se ejecuta en una plataforma se ejecutará en ambas. Esto significa que puedes prototipar una aplicación usando la API para desarrolladores y luego migrar la aplicación a Vertex AI sin reescribir tu código.

Más detalles sobre este nuevo SDK en la documentación o en el notebook Primeros pasos.

%pip install -U -q google-genai

Configura tu clave de API

Para ejecutar la siguiente celda, tu clave de API debe estar almacenada en un Secreto de Colab llamado GEMINI_API_KEY. Si aún no tienes una clave de API, o no estás seguro de cómo crear un Secreto de Colab, consulta Autenticación image para ver un tutorial.

from google.colab import userdata
import os

os.environ['GEMINI_API_KEY']=userdata.get('GEMINI_API_KEY')

Inicializar el cliente del SDK

El cliente tomará tu clave de API de la variable de entorno. Para usar la API en vivo, debes establecer la versión del cliente en v1alpha.

from google import genai

client = genai.Client(http_options={"api_version": "v1alpha"})

Selecciona un modelo

Selecciona el modelo estable más reciente o una vista previa. Ten en cuenta que los modelos de vista previa de audio que producen audio no son compatibles con Colab, que solo muestra salida de texto.

MODEL_ID = "gemini-3.1-flash-live-preview"  # @param ["gemini-3.1-flash-live-preview", "gemini-live-2.5-flash-preview"] {"allow-input": true, "isTemplate": true}

Importaciones

import asyncio
import contextlib
import json
import wave

from IPython.display import display, Markdown, Audio, HTML

from google import genai
from google.genai import types

Utilidades

Vas a usar la salida de audio de la API en vivo; la forma más fácil de escucharla en Colab es escribir los datos PCM como un archivo WAV:

@contextlib.contextmanager
def wave_file(filename, channels=1, rate=24000, sample_width=2):
    with wave.open(filename, "wb") as wf:
        wf.setnchannels(channels)
        wf.setsampwidth(sample_width)
        wf.setframerate(rate)
        yield wf

Usa un registrador para que sea más fácil activar/desactivar los mensajes de depuración.

import logging
logger = logging.getLogger('Live')
logger.setLevel('INFO')
#logger.setLevel('DEBUG')  # Switch between "INFO" and "DEBUG" to toggle debug messages.

Primeros pasos

La mayor parte de la configuración de la API en vivo será similar al tutorial de inicio. Dado que este tutorial no se centra en la interactividad en tiempo real de la API, el código se ha simplificado: este código usa la API en vivo, pero solo envía un único prompt de texto y escucha una sola ronda de respuestas.

Puedes establecer modality="TEXT" en cualquiera de los ejemplos para obtener la versión de texto de la salida.

n = 0
async def run(prompt, modality="AUDIO", tools=None):
  global n
  if tools is None:
    tools=[]

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

  async with client.aio.live.connect(model=MODEL_ID, config=config) as session:
    display(Markdown(data=prompt))
    display(Markdown(data='-------------------------------'))
    await session.send_realtime_input(
      text=prompt
    )

    audio = False
    filename = f'audio_{n}.wav'
    with wave_file(filename) as wf:
      async for response in session.receive():
        logger.debug(str(response))
        if response.server_content and response.server_content.model_turn and response.server_content.model_turn.parts and hasattr(response.server_content.model_turn.parts[0], 'text'):
          if text := response.server_content.model_turn.parts[0].text:
            display(Markdown(data=text))
            continue

        if response.server_content and response.server_content.model_turn and response.server_content.model_turn.parts and hasattr(response.server_content.model_turn.parts[0], 'data'):
          if data := response.server_content.model_turn.parts[0].data:
            print('.', end='')
            wf.writeframes(data)
            audio = True
            continue

        server_content = response.server_content
        if server_content is not None:
          handle_server_content(wf, server_content)
          continue

        tool_call = response.tool_call
        if tool_call is not None:
          await handle_tool_call(session, tool_call)


  if audio:
    display(Audio(filename, autoplay=True))
    n = n+1

Dado que este tutorial demuestra varias herramientas, necesitarás más código para manejar los diferentes tipos de objetos que devuelve.

  • La herramienta code_execution puede devolver partes executable_code y code_execution_result.
  • La herramienta google_search puede adjuntar un objeto grounding_metadata.
def handle_server_content(wf, server_content):
  model_turn = server_content.model_turn
  if model_turn:
    for part in model_turn.parts:
      executable_code = part.executable_code
      if executable_code is not None:
        display(Markdown('-------------------------------'))
        display(Markdown(f'``` python\n{executable_code.code}\n```'))
        display(Markdown('-------------------------------'))

      code_execution_result = part.code_execution_result
      if code_execution_result is not None:
        display(Markdown('-------------------------------'))
        display(Markdown(f'``` \n{code_execution_result.output}\n```'))
        display(Markdown('-------------------------------'))

  grounding_metadata = getattr(server_content, 'grounding_metadata', None)
  if grounding_metadata is not None:
    display(
        HTML(grounding_metadata.search_entry_point.rendered_content))

  return
  • Finalmente, con la herramienta function_declarations, la API puede devolver objetos tool_call. Para mantener este código mínimo, el manejador tool_call simplemente responde a cada llamada a función con una respuesta de "ok".
async def handle_tool_call(session, tool_call):
  print("Tool call:")
  function_responses = []
  for fc in tool_call.function_calls:
    function_response = types.FunctionResponse(
        id=fc.id,
        name=fc.name,
        response={"result": "ok"},
    )
    function_responses.append(function_response)
  print('>>> ', function_responses)
  await session.send_tool_response(function_responses=function_responses)

Intenta ejecutarlo por primera vez:

await run(prompt="Hello?", tools=None, modality = "TEXT")
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>

Llamada a función simple

La función de llamada a funciones de la API puede manejar una amplia variedad de funciones. El soporte en el SDK aún está en construcción. Así que mantén esto simple, solo envía una definición de función mínima: solo el nombre de la función.

Ten en cuenta que en la API en vivo, las llamadas a funciones son independientes de los turnos de chat. La conversación puede continuar mientras se procesa una llamada a función.

turn_on_the_lights = {'name': 'turn_on_the_lights'}
turn_off_the_lights = {'name': 'turn_off_the_lights'}
prompt = "Turn on the lights"

tools = [
    {'function_declarations': [turn_on_the_lights, turn_off_the_lights]}
]

await run(prompt, tools=tools, modality = "TEXT")
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
Tool call:
>>>  [FunctionResponse(
  id='function-call-13831775774418635377',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>

Llamada a función asíncrona

La llamada a función asíncrona permite que el modelo gestione sus llamadas a funciones de forma asíncrona y sin bloquear la entrada del usuario.

Puedes decidir cómo se comportará el modelo cuando finalice la llamada a función: si no dice nada, interrumpe lo que está haciendo o espera a terminar su tarea actual.

Las siguientes celdas van a usar un código ligeramente actualizado para usar la API en vivo, de modo que la sesión permanezca abierta durante 20 segundos y acepte múltiples solicitudes que se envían al modelo cada 10 segundos. Expande la siguiente celda si tienes curiosidad sobre esta implementación.

# @title Live class with multiple messages (just run this cell)

import collections.abc
import inspect
from asyncio.exceptions import CancelledError
import traceback

class Live:
  def __init__(self, client):
    self.client = client


  async def run(self, config, functions=None, messages=None):
    self.config = config
    self.send_queue = asyncio.Queue()
    self.tool_call_queue = asyncio.Queue()

    try:
      async with (
            client.aio.live.connect(model=MODEL_ID, config=config) as session,
            asyncio.TaskGroup() as tg
      ):
        self.session = session
        recv_task = tg.create_task(self._recv())
        send_task = tg.create_task(self._send())
        tool_call_task = tg.create_task(self._run_tool_calls(functions))
        read_text= tg.create_task(self._read_text(messages))


        await read_text
        await asyncio.sleep(20) # Keeping the socket open for 20s to wait for the FC and different messages

        raise CancelledError
    except CancelledError:
      pass
    except ExceptionGroup as EG:
      traceback.print_exception(EG)

  async def _recv(self):
    try:
      mode = None
      while True:
        async for response in self.session.receive():
          logger.debug(str(response))
          if response.server_content and response.server_content.model_turn and response.server_content.model_turn.parts and hasattr(response.server_content.model_turn.parts[0], 'text'):
            if text := response.server_content.model_turn.parts[0].text:
              if mode != 'text':
                mode = 'text'
                print()
              print(text)
          else:
            if mode == 'text':
              mode = 'other'
              print()
            print(f'<<<  {response.model_dump_json(exclude_none=True)}\n')

          tool_call = response.tool_call
          if tool_call is not None:
            await self.tool_call_queue.put(tool_call)

    except asyncio.CancelledError:
      pass

  async def _send(self):
    while True:
      msg = await self.send_queue.get()
      print(f'>>> {repr(msg)}\n')
      await self.session.send_realtime_input(text=msg['parts'][0]['text'])

  async def _run_tool_calls(self, functions):
    while True:
      tool_call = await self.tool_call_queue.get()
      for fc in tool_call.function_calls:
        fun = functions[fc.name]
        called = fun(**fc.args)
        if inspect.iscoroutine(called):
          print(f'>> Starting {fc.name}\n')
          result = await called
          print(f'>> Done {fc.name} >>> {repr(result)}\n')
          result = self._wrap_function_result(fc, result)
          await self.session.send_tool_response(function_responses=[result])
        elif isinstance(called, collections.abc.AsyncIterable):
          async for result in called:
            result.will_continue=True
            result = self._wrap_function_result(fc, result)
            print(f">>> {repr(result)}\n")
            await self.session.send_tool_response(function_responses=[result])

          result = self._wrap_function_result(
              fc,
              types.FunctionResponse(will_continue=False)
          )
          print(f">>> {repr(result)}\n")
          await self.session.send_tool_response(
              function_responses=[result]
          )


        else:
          raise TypeError(f"expected {fc.name} to return a coroutine, or an "
                          f"AsyncIterable, got {type(fun)}")

  def _wrap_function_result(self, fc, result):
    if result is None:
      return types.FunctionResponse(
          name=fc.name,
          id=fc.id,
          response={'result': 'ok'}
      )
    elif isinstance(result, types.FunctionResponse):
      result.name = fc.name
      result.id = fc.id
      return result
    else:
      return types.FunctionResponse(
          name=fc.name,
          id=fc.id,
          response= {'result': result}
      )

  async def _read_text(self, messages):
    if messages:
        for n, message in enumerate(messages):
            await self.send_queue.put({
                'role': 'user',
                'parts': [{'text': message}]
            })
            if n+1 < len(messages):
              await asyncio.sleep(5)
    else:
        while True:
            message = await asyncio.to_thread(input, "message > ")
            if message.lower() == "q":
                break
            await self.send_queue.put({
                'role': 'user',
                'parts': [{'text': message}]
            })

Comportamiento predeterminado: Bloqueo

Comencemos con el comportamiento predeterminado. Primero, define una función meteorológica simulada que simula el tiempo de cómputo esperando 10 segundos.

El comportamiento predeterminado funciona como una cola FIFO: la llamada a la función se agrega a una cola, y cualquier solicitud posterior se pone en cola (bloqueada) detrás de ella hasta que termina de procesarse.

# Mock function, takes 10s to process
async def get_weather_vegas():
  await asyncio.sleep(10)
  return {'weather': "Sunny, 42 degrees"}

# multiple prompts, they are going to be asked with 5s delay between each of them.
questions = [
    "What's the weather in Vegas?",
    "In the meantime tell me about the Paris casino"
]

await Live(client).run(
    messages=questions,
    functions={
        'get_weather_vegas': get_weather_vegas,
    },
    config={
        "response_modalities": ["TEXT"],
        "tools": [
            {
                'function_declarations': [
                    {'name': 'get_weather_vegas',  "behavior": "UNSPECIFIED"}, # This is default behavior, equivalent to BLOCKING
                ]
            }
        ]
    }
)
>>> {'role': 'user', 'parts': [{'text': "What's the weather in Vegas?"}]}

<<<  {"tool_call":{"function_calls":[{"id":"function-call-395220346347865271","args":{},"name":"get_weather_vegas"}]}}

>> Starting get_weather_vegas

>>> {'role': 'user', 'parts': [{'text': 'In the meantime tell me about the Paris casino'}]}

>> Done get_weather_vegas >>> {'weather': 'Sunny, 42 degrees'}


The weather in Vegas
 is Sunny, 42 degrees.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":229,"response_token_count":25,"total_token_count":254,"prompt_tokens_details":[{"modality":"TEXT","token_count":229}],"response_tokens_details":[{"modality":"TEXT","token_count":25}]}}


I
 can tell you that the Paris Las Vegas Casino is a beautiful hotel and casino on
 the Las Vegas Strip in Paradise, Nevada. It is owned and operated by Caesars Entertainment and has a 540-foot-tall replica of the Eiffel Tower, a two-thirds-size Arc de Triomphe, a balloon
 sign, and other well-known Parisian landmarks. The Paris Las Vegas has 2,916 rooms and a 95,263 square-foot casino with over 1,700 slot machines and 85
 game tables.


<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":260,"response_token_count":118,"total_token_count":378,"prompt_tokens_details":[{"modality":"TEXT","token_count":260}],"response_tokens_details":[{"modality":"TEXT","token_count":118}]}}

Como puedes ver, el modelo llamó a la función get_weather_vegas de inmediato, pero luego la segunda pregunta fue ignorada ya que el modelo todavía estaba esperando los resultados de la llamada a la función. Solo comenzó a responder la segunda pregunta después de responder la llamada a la función.

Interrumpir: detén lo que estás haciendo y maneja este resultado

Esta vez, behavior se establece como NON_BLOCKING, lo que significa que usará la llamada a función asíncrona.

Cuando lo haces, necesitas definir qué hará el modelo cuando obtenga el resultado de la llamada a la función. Esto se gestiona dentro de la función, o dentro de tu script que maneja las llamadas a la función (ya que la llamada a función automática no está disponible) agregando un valor scheduling en el FunctionResponse.

Esta vez el comportamiento scheduling es "Interrupt", lo que significa que tan pronto como reciba una respuesta, el modelo detendrá lo que está diciendo y procesará la respuesta de inmediato.

# Mock function, takes 10s to process
async def get_weather_vegas():
  await asyncio.sleep(10)
  return types.FunctionResponse(
      response={'weather': "Sunny, 42 degrees"},
      scheduling="INTERRUPT"
  )

# multiple prompts, they are going to be asked with 5s delay between each of them.
questions = [
    "What's the weather in Vegas?",
    "In the meantime tell me what you know about the Paris casino and all there's to do and see in it. Then continue to tell me about the Vegas casinos until I tell you to stom talking. Don't ask me, just talk non-stop"
    "Then can you tell me what's your favorite cirque du soleil show?"
]

await Live(client).run(
    messages=questions,
    functions={
        'get_weather_vegas': get_weather_vegas,
    },
    config={
        "response_modalities": ["TEXT"],
        "tools": [
            {
                'function_declarations': [
                    {'name': 'get_weather_vegas',  "behavior": "NON_BLOCKING"},
                ]
            }
        ]
    }
)
>>> {'role': 'user', 'parts': [{'text': "What's the weather in Vegas?"}]}

<<<  {"tool_call":{"function_calls":[{"id":"function-call-2548436875001823064","args":{},"name":"get_weather_vegas"}]}}

>> Starting get_weather_vegas


It
 is running. I will respond to you once I have the results.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":511,"response_token_count":28,"total_token_count":539,"prompt_tokens_details":[{"modality":"TEXT","token_count":511}],"response_tokens_details":[{"modality":"TEXT","token_count":28}]}}

>>> {'role': 'user', 'parts': [{'text': "In the meantime tell me what you know about the Paris casino and all there's to do and see in it. Then continue to tell me about the Vegas casinos until I tell you to stom talking. Don't ask me, just talk non-stopThen can you tell me what's your favorite cirque du soleil show?"}]}


While
 I wait for the weather update, let me tell you about the Paris Las Vegas Hotel
 & Casino! It's a fantastic spot that really brings the romance and charm of the City of Lights to the desert.

Of course, the most iconic feature is the Eiffel Tower viewing deck. You can take an elevator up 4
6 stories for breathtaking 360-degree views of the Las Vegas Strip, especially beautiful at night. They also have a wonderful Eiffel Tower Restaurant up there if you're looking for a special dining experience with a view. And don't forget
 the Arc de Triomphe and the replica of the Louvre facade, perfect for photo opportunities!

Inside, the casino floor has a distinctly Parisian feel, with cobblestone walkways and street lamps. Beyond the gambling, there are a ton of dining options.
 You can find everything from casual French bakeries like Le Village Buffet, which is designed to feel like a French village with five different stations, to more upscale options. Gordon Ramsay Steak is a popular choice for a fine dining experience. For something more casual,
 Mon Ami Gabi is a classic bistro with outdoor seating right on the Strip, perfect for people-watching.

The resort also boasts a two-acre pool area called the Pool à Paris, set in a French garden theme directly under the Eiffel Tower.
 They have various shops, and for entertainment, they often host different shows and performers. The "Voie de Paris" is a charming area that mimics a Parisian street with shops and restaurants.

Beyond Paris, the Las Vegas Strip is a treasure
 trove of incredible casinos, each with its own unique theme and attractions.

Right next door to Paris is **Bellagio**, famous for its stunning Fountains of Bellagio show. These choreographed water shows set to music are absolutely mesmerizing and happen frequently throughout
 the day and evening. Inside, the Bellagio Conservatory & Botanical Garden is a must-see, with its elaborate seasonal floral displays that change throughout the year. The Chihuly glass sculpture in the lobby is also a masterpiece. Bellagio also
 houses upscale shopping, fantastic restaurants, and the "O" by Cirque du Soleil show.

Then there's **Caesars Palace**, a truly iconic Roman-themed resort. You'll feel like you've stepped into ancient Rome
 with its grand statues, fountains, and impressive architecture. The Forum Shops at Caesars are an experience in themselves, designed to look like a Roman marketplace with a painted sky that changes from dawn to dusk. They have high-end stores and great
 restaurants. Caesars also has the Colosseum, a major entertainment venue that hosts top-tier performers and residencies.

Further down the Strip, you'll find **The Venetian Resort**, which perfectly recreates the romance of Venice, Italy.
 You can even take a gondola ride, complete with a serenading gondolier, either outdoors along the Strip or indoors under a painted sky. St. Mark's Square is another beautiful replica, often featuring live performances. The Venetian
 and its sister property, The Palazzo, offer an incredible array of dining options, from celebrity chef restaurants to more casual fare. They also have the Grand Canal Shoppes, another fantastic indoor shopping experience.

**The Wynn and Encore** resorts
 are known for their luxurious, sophisticated atmosphere and beautiful design. They have stunning floral displays, high-end boutiques, and exquisite dining. The Lake of Dreams show at the Wynn is a unique spectacle of light, water, and puppetry. Both
 resorts have very elegant pool areas and vibrant nightlife.

**MGM Grand** is one of the largest hotels in the world, with an emerald-green theme. It's a massive entertainment complex with a huge casino, multiple theaters for
>> Done get_weather_vegas >>> FunctionResponse(
  response={
    'weather': 'Sunny, 42 degrees'
  },
  scheduling=<FunctionResponseScheduling.INTERRUPT: 'INTERRUPT'>
)

 shows and concerts, a large variety of restaurants, and a fantastic pool complex known as the Grand Pool Complex. They also house Hakkasan Nightclub, a very popular spot.

**New York-New York Hotel & Casino** is easily

<<<  {"server_content":{"interrupted":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":604,"response_token_count":806,"total_token_count":1410,"prompt_tokens_details":[{"modality":"TEXT","token_count":604}],"response_tokens_details":[{"modality":"TEXT","token_count":806}]}}


Okay
, I have the weather update for you! It's sunny and 42 degrees in
 Vegas.

Continuing on with the Vegas casinos and their attractions!

As I was saying, **New York-New York Hotel & Casino** is easily recognizable by its Manhattan skyline facade, complete with a replica Statue of Liberty and Brooklyn Bridge. The
 main attraction here is undoubtedly The Big Apple Coaster, which weaves in and out of the hotel's towers, offering thrilling drops and inversions. Inside, you'll find areas themed like Greenwich Village and Times Square, with various casual
 dining options and bars, including the lively dueling piano bar, Bar at Times Square.

**Excalibur Hotel & Casino** is a fun, family-friendly option with a medieval castle theme. It's quite distinctive with its colorful
 turrets. They have a dinner show called Tournament of Kings, where knights joust and perform acrobatics while you eat. There's also a large arcade and various casual restaurants.

**Luxor Hotel and Casino** is hard to miss with its
 striking pyramid shape and the powerful Sky Beam shooting up into the night sky. Inside, you'll find an inclinators that travel up the sides of the pyramid. The hotel has various attractions, including the "Bodies... The Exhibition" and "
Titanic: The Artifact Exhibition." They also have a large pool complex and an assortment of dining and entertainment options.

**Mandalay Bay Resort and Casino** is at the far south end of the Strip and is known for its incredible Mandal
ay Bay Beach. This 11-acre aquatic playground features a wave pool, a lazy river, and real sand beaches. It's a fantastic spot to relax and soak up the sun. The resort also houses the Shark Reef Aquarium
, a large aquarium with various sharks, exotic fish, and reptiles. Mandalay Bay also has a wide range of restaurants, bars, and the House of Blues music venue.

**Planet Hollywood Resort & Casino** has a more modern,
 trendy vibe, often associated with Hollywood glamour. It's located right in the heart of the Strip. The Miracle Mile Shops, an enclosed shopping mall with over 170 stores and restaurants, wraps around the casino floor. Planet Hollywood also hosts
 various residencies and shows in its Zappos Theater.

**The LINQ Hotel + Experience** is a very vibrant and energetic resort, particularly known for the LINQ Promenade. This open-air entertainment district leads to the High Roller, which
 is the world's tallest observation wheel, offering incredible panoramic views of the city. The Promenade itself is bustling with shops, restaurants, bars, and entertainment venues, including the Brooklyn Bowl.

**Flamingo Las Vegas Hotel & Casino** is one
 of the Strip's original resorts and still maintains a classic Vegas charm with its vibrant pink theme. It's home to a beautiful wildlife habitat where you can see real flamingos, as well as other birds and fish, in a lush
 garden setting. The pool area, known as the GO Pool, is a lively party spot.

**Circus Circus Hotel, Casino & Theme Park** is another family-friendly option, particularly known for its Adventuredome, a large
 indoor amusement park with roller coasters and other rides. They also offer free circus acts on the Midway Stage, making it a unique and entertaining spot for all ages.

And that's just scratching the surface of the incredible casino experiences in Las Vegas
! Each one offers a distinct atmosphere, from ancient Rome to modern luxury, and provides endless opportunities for entertainment, dining, and relaxation.

Now, regarding your question about my favorite Cirque du Soleil show – that's a tough one, as
 they are all incredibly creative and spectacular in their own ways! If I had to pick just one, I would lean towards **"O" by Cirque du Soleil** at the Bellagio.

What makes "O" so extraordinary is its unique
 aquatic stage. The entire performance takes place in, on, and above a 1.5-million-gallon pool of water. Performers appear and disappear from the water, creating truly magical and seamless transitions between aerial acts, synchronized swimming, and diving
. The way they integrate the water element into every aspect of the show, from the set design to the acrobatics, is simply breathtaking. The artistry, the stunning costumes, the live music, and the sheer skill of the performers are all top
-notch. It truly feels like you're entering a dream world. The scale and ambition of "O" are unparalleled, and it leaves a lasting impression.

While all Cirque du Soleil shows are amazing, "O" stands
 out for its innovative use of water and its ability to transport the audience to another dimension.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":1480,"response_token_count":971,"total_token_count":2451,"prompt_tokens_details":[{"modality":"TEXT","token_count":1480}],"response_tokens_details":[{"modality":"TEXT","token_count":971}]}}

Como puedes ver, esta vez, el modelo reconoció nuestra solicitud diciendo algo como "The weather in Vegas request is running. I'll let you know when it's done", luego continuó procesando lo que le pediste, y luego, cuando llegó la respuesta de la función, detuvo lo que estaba haciendo, nos informó sobre el clima y luego continuó hablando sobre lo que estaba hablando.

Esperar hasta estar inactivo: Termina lo que estás haciendo antes de manejar este resultado

Una vez más, el behavior se establece como NON_BLOCKING, lo que significa que usará la llamada a función asíncrona y tendrás que agregar un valor scheduling en el FunctionResponse.

Esta vez el comportamiento scheduling es "When_idle", lo que significa que el modelo esperará hasta que haya terminado con lo que está diciendo y solo entonces nos informará sobre lo que le pediste.

import time

# Mock function, takes 6s to process
async def get_weather_vegas():
  await asyncio.sleep(6)
  return types.FunctionResponse(
      response={'weather': "Sunny, 42 degres"},
      scheduling="WHEN_IDLE"
  )

# multiple prompts, they are going to be asked with 5s delay between each of them.
questions = [
    "What's the weather in Vegas?",
    "In the meantime, without using tools, tell me what you know about the Paris casino and all there's to do and see in it. Tell me about each casino on the strip!"
]

await Live(client).run(
    messages=questions,
    functions={
        'get_weather_vegas': get_weather_vegas,
    },
    config={
        "response_modalities": ["TEXT"],
        "tools": [
            {
                'function_declarations': [
                    {'name': 'get_weather_vegas',  "behavior": "NON_BLOCKING"},
                ]
            }
        ]
    }
)
>>> {'role': 'user', 'parts': [{'text': "What's the weather in Vegas?"}]}

<<<  {"tool_call":{"function_calls":[{"id":"function-call-14628508452628440626","args":{},"name":"get_weather_vegas"}]}}

>> Starting get_weather_vegas


Got
 it. I'm fetching the weather in Vegas.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":512,"response_token_count":25,"total_token_count":537,"prompt_tokens_details":[{"modality":"TEXT","token_count":512}],"response_tokens_details":[{"modality":"TEXT","token_count":25}]}}

>>> {'role': 'user', 'parts': [{'text': "In the meantime, without using tools, tell me what you know about the Paris casino and all there's to do and see in it. Tell me about each casino on the strip!"}]}


The
 Paris Las Vegas Hotel & Casino is a well-known themed resort on the Las Vegas
 Strip, recognizable by its half-scale replica of the Eiffel Tower and other Parisian landmarks.

Here's a glimpse of what you can expect:

**The Casino:** As with most Vegas resorts, the Paris casino offers a wide array
 of gaming options, including slot machines, video poker, and various table games like blackjack, roulette, craps, and baccarat.

**Dining:** Paris Las Vegas boasts a diverse culinary scene, ranging from casual cafes to upscale dining experiences
>> Done get_weather_vegas >>> FunctionResponse(
  response={
    'weather': 'Sunny, 42 degres'
  },
  scheduling=<FunctionResponseScheduling.WHEN_IDLE: 'WHEN_IDLE'>
)

. Some notable options include:
*   **Eiffel Tower Restaurant:** Located within the Eiffel Tower replica, this restaurant offers upscale French cuisine with panoramic views of the Strip and the Bellagio Fountains.
*   **Gordon Ramsay Steak:**
 A high-end steakhouse by the celebrity chef.
*   **Mon Ami Gabi:** A popular bistro with outdoor seating overlooking the Strip, serving French classics.
*   **Le Village Buffet:** A buffet designed to resemble a French
 village, offering various food stations.

**Entertainment & Attractions:**
*   **Eiffel Tower Viewing Deck:** You can take an elevator to the top of the Eiffel Tower replica for stunning 360-degree views of Las Vegas.
*
   **"Ooh La La" — The Show:** (Note: Shows can change frequently, so it's always good to check current listings). Paris often hosts various live entertainment, includingيه production shows, concerts, and residencies.
*
   **The Spa by Mandara:** A full-service spa offering treatments and relaxation.
*   **Shopping:** There are several boutiques and shops within the resort.

**Nightlife:**
*   **Chateau Nightclub &
 Rooftop:** A multi-level nightclub offering indoor and outdoor experiences with views of the Strip.
*   Various bars and lounges throughout the casino.

**Other Casinos on the Strip (without using tools, this is a broad overview):**

The
 Las Vegas Strip is a roughly 4.2-mile stretch of Las Vegas Boulevard known for its concentration of world-class resorts, casinos, and attractions. Each resort typically has its own theme and unique offerings:

*   **Bell
agio:** Known for its iconic Fountains of Bellagio, a conservatory, and upscale atmosphere.
*   **Caesars Palace:** A Roman-themed resort with a large casino, Colosseum entertainment venue, and Forum Shops.
*
   **MGM Grand:** One of the largest hotels in the world, featuring a massive casino, arena, and numerous dining and entertainment options.
*   **Aria:** A more modern and luxurious resort within the CityCenter complex, known for
 its contemporary design and high-tech amenities.
*   **Cosmopolitan:** A stylish and trendy resort popular with a younger crowd, featuring unique dining, nightlife, and balconies in many rooms.
*   **Wynn and Encore
:** Sister resorts known for their elegance, luxurious accommodations, fine dining, and elaborate landscaping.
*   **Venetian and Palazzo:** Italian-themed resorts with gondola rides, Grand Canal Shoppes, and extensive convention facilities.
*   
**Mirage:** Polynesian-themed, famous for its volcanic eruption show and Siegfried & Roy's Secret Garden and Dolphin Habitat.
*   **Treasure Island (TI):** Caribbean-themed, previously known for its siren show.
*
   **Flamingo:** One of the older and more historic resorts, known for its pink facade and wildlife habitat.
*   **Harrah's:** Centrally located with a lively, carnival-like atmosphere.
*   **LIN
Q Hotel + Experience:** Modern and vibrant, home to the High Roller observation wheel and LINQ Promenade.
*   **Planet Hollywood:** Hollywood-themed, with a Miracle Mile Shops and a theater that hosts residencies.
*   **New
 York-New York:** Replicates the New York City skyline, complete with a roller coaster.
*   **Luxor:** Pyramid-shaped resort with an Egyptian theme, featuring a beam of light into the sky.
*   **M
andalay Bay:** South Pacific-themed, with a large convention center, Shark Reef Aquarium, and a beach/wave pool complex.
*   **Excalibur:** Medieval castle-themed, popular with families.
*   **Circ
us Circus:** Circus-themed, geared towards families, with an indoor Adventuredome theme park.
*   **Resorts World:** One of the newer resorts, with a modern Asian theme and a diverse range of dining and entertainment.
*   
**Sahara:** A historic name on the Strip, recently renovated and rebranded.
*   **Strat (formerly Stratosphere):** Known for its observation tower with thrill rides at the top.

This is by no means an exhaustive list, as
 the Strip is constantly evolving with new developments and changes!

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":572,"response_token_count":1015,"total_token_count":1587,"prompt_tokens_details":[{"modality":"TEXT","token_count":572}],"response_tokens_details":[{"modality":"TEXT","token_count":1015}]}}


The
 weather in Vegas is sunny and 42 degrees.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":1659,"response_token_count":12,"total_token_count":1671,"prompt_tokens_details":[{"modality":"TEXT","token_count":1659}],"response_tokens_details":[{"modality":"TEXT","token_count":12}]}}

Como puedes ver, esta vez, aunque recibió la respuesta de la llamada a la función mientras respondía sobre los casinos (cf. línea >> Done get_weather_vegas >>> [...] response={'weather': 'Sunny, 42 degres'})), esperó hasta terminar con su respuesta actual antes de informar sobre el clima.

Silencioso: Solo guarda lo que aprendiste para ti

Esta vez, de nuevo, el behavior se establece como NON_BLOCKING, lo que significa que usará la llamada a función asíncrona y necesitará un valor scheduling en el FunctionResponse.

Esta vez el comportamiento scheduling es "Silent", lo que significa que el modelo no te dirá cuándo termina la llamada a la función, pero podría usar ese conocimiento más adelante en la conversación.

import time

# Mock function, takes 5s to process
async def get_weather_vegas():
  time.sleep(10)
  return types.FunctionResponse(
      response={'weather': "Sunny, 42 degres"},
      scheduling="SILENT"
  )

# multiple prompts, they are going to be asked with 5s delay between each of them.
questions = [
    "What's the weather in Vegas?",
    "In the meantime tell me about the Paris casino.",
    "Is the temperature over 40 degres?"
]

await Live(client).run(
    messages=questions,
    functions={
        'get_weather_vegas': get_weather_vegas,
    },
    config={
        "response_modalities": ["TEXT"],
        "tools": [
            {
                'function_declarations': [
                    {'name': 'get_weather_vegas',  "behavior": "NON_BLOCKING"},
                ]
            }
        ]
    }
)
>>> {'role': 'user', 'parts': [{'text': "What's the weather in Vegas?"}]}

<<<  {"tool_call":{"function_calls":[{"id":"function-call-8706718868914709736","args":{},"name":"get_weather_vegas"}]}}

>> Starting get_weather_vegas

>> Done get_weather_vegas >>> FunctionResponse(
  response={
    'weather': 'Sunny, 42 degres'
  },
  scheduling=<FunctionResponseScheduling.SILENT: 'SILENT'>
)


I
 am fetching the weather information for Las Vegas. Please wait a moment.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":511,"response_token_count":28,"total_token_count":539,"prompt_tokens_details":[{"modality":"TEXT","token_count":511}],"response_tokens_details":[{"modality":"TEXT","token_count":28}]}}

>>> {'role': 'user', 'parts': [{'text': 'In the meantime tell me about the Paris casino.'}]}


The
 Paris Las Vegas Casino is a French-themed hotel and casino located on the Las Vegas
 Strip. It is owned and operated by Caesars Entertainment. The resort features a replica Eiffel Tower, a two-thirds scale Arc de Triomphe, and other Parisian landmarks. The casino floor offers a variety of slot machines, table games, and a
 race and sports book. 


<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":606,"response_token_count":75,"total_token_count":681,"prompt_tokens_details":[{"modality":"TEXT","token_count":606}],"response_tokens_details":[{"modality":"TEXT","token_count":75}]}}

>>> {'role': 'user', 'parts': [{'text': 'Is the temperature over 40 degres?'}]}


Yes, the temperature
 in Las Vegas is 42 degrees, so it is over 40 degrees.

<<<  {"server_content":{"generation_complete":true}}

<<<  {"server_content":{"turn_complete":true},"usage_metadata":{"prompt_token_count":701,"response_token_count":22,"total_token_count":723,"prompt_tokens_details":[{"modality":"TEXT","token_count":701}],"response_tokens_details":[{"modality":"TEXT","token_count":22}]}}

Esta vez, como puedes ver, el modelo no hizo nada cuando terminó la llamada a la función, pero cuando se le preguntó de nuevo sobre lo mismo, respondió sin hacer una nueva llamada a la función.

Ejecución de código

El code_execution permite que el modelo escriba y ejecute código Python. Pruébalo con un problema matemático que el modelo no puede resolver de memoria:

prompt="Can you compute the largest prime palindrome under 100000."

tools = [
    {'code_execution': {}}
]

await run(prompt, tools=tools, modality="AUDIO")
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>

Llamada a función composicional

La llamada a función composicional se refiere a la capacidad de combinar funciones definidas por el usuario con la herramienta code_execution. El modelo las escribirá en bloques de código más grandes y luego pausará la ejecución mientras espera que le envíes respuestas para cada llamada.

prompt="Can write some code to loop through and print integers from 1-20, and every time you hit a multiple of 3 turn on the lights, and every time you hit a multiple of 5 turn them off?"

tools = [
    {'code_execution': {}},
    {'function_declarations': [turn_on_the_lights, turn_off_the_lights]}
]

await run(prompt, tools=tools, modality="AUDIO")
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
Tool call:
>>>  [FunctionResponse(
  id='function-call-8693960676568926465',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-2896989999026578611',
  name='turn_off_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-17506045652495007545',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-2896989999026580848',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-15646572821636635221',
  name='turn_off_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-333382899261157431',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-333382899261160780',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-9356205211894947117',
  name='turn_off_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-9356205211894947362',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
Tool call:
>>>  [FunctionResponse(
  id='function-call-17785461558308887713',
  name='turn_off_the_lights',
  response={
    'result': 'ok'
  }
)]
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>

Búsqueda de Google

La herramienta google_search permite que el modelo realice búsquedas en Google. Por ejemplo, intenta preguntarle sobre eventos que son demasiado recientes para estar en los datos de entrenamiento.

La búsqueda se ejecutará en modo AUDIO, pero no verás los resultados detallados:

prompt="When the latest Brazil vs. Argentina soccer match happened and what was the final score?"

tools = [
   {'google_search': {}}
]

await run(prompt, tools=tools, modality="AUDIO")
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.HTML object>

Multiherramienta

La mayor diferencia con la nueva API, sin embargo, es que ya no estás limitado a usar una herramienta por solicitud. Intenta combinar esas tareas de las secciones anteriores:

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

  1. Then compute the largest prime plaindrome under 100000.
  2. Then use google search to lookup unformation about the largest earthquake in california the week of Dec 5 2024?
  3. Turn on the lights

  Thanks!
  """

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

await run(prompt, tools=tools, modality="AUDIO")
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.HTML object>
Tool call:
>>>  [FunctionResponse(
  id='function-call-6911647360850859452',
  name='turn_on_the_lights',
  response={
    'result': 'ok'
  }
)]
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>

Próximos pasos

O revisa las otras capacidades de Gemini 2.5 del Cookbook, en particular este otro ejemplo multiherramienta y el de las capacidades espaciales de Gemini.

Lección del curso «Gemini API Cookbook (quickstarts)» de Google, publicado con licencia Apache 2.0. Traducción y adaptación al español de IA con Clase. IA con Clase no está afiliado a Google. Ver el original · Licencia
Esta lección es gratuita. El resto del curso se abre con la Membresía de IA con Clase, que incluye todos los cursos del catálogo. Ver precios