Instructivo sobre llamadas a funciones

Las llamadas a función facilitan la obtención de resultados de datos estructurados desde generativos. Luego, puedes usar estos resultados para llamar a otras APIs y mostrar los datos de respuesta relevantes para el modelo. En otras palabras, las llamadas a funciones ayudan conecta modelos generativos a sistemas externos para que el contenido generado incluya la información más actualizada y precisa.

Puedes proporcionarles descripciones de funciones a los modelos de Gemini. Son funciones que escribes en el lenguaje de tu app (es decir, Google Cloud Functions). El modelo puede pedirte que llames a una función y devuelvas el resultado para ayudar al modelo a manejar tu consulta.

Si aún no lo has hecho, consulta la Introducción a la llamada a función para aprender más. También puedes prueba esta función en Google Colab o mira el código de ejemplo en la Repositorio de la Guía de soluciones de la API de Gemini.

API de ejemplo para control de iluminación

Imagina que tienes un sistema de control de iluminación básico con una aplicación (API), y quieres permitir que los usuarios controlen las luces mediante solicitudes de texto. Puedes usar la función Llamadas a función para interpretar la iluminación las solicitudes de cambio de los usuarios y traducirlas en llamadas a la API para establecer la iluminación de salida. Este hipotético sistema de control de iluminación te permite controlar la el brillo de la luz y su temperatura de color, que se definen como dos parámetros:

Parámetro Tipo Obligatorio Descripción
brightness número Nivel de luz de 0 a 100. El cero está desactivado y el 100 es el brillo total.
colorTemperature string Es la temperatura del color de la lámpara, que puede ser daylight, cool o warm.

Para simplificar, este sistema de iluminación imaginario solo tiene una luz, por lo que el usuario no necesita especificar una sala o ubicación. Este es un ejemplo de una solicitud JSON podrías enviar a la API de control de iluminación para cambiar el nivel de luz al 50% usando la temperatura de color de la luz diurna:

{
  "brightness": "50",
  "colorTemperature": "daylight"
}

En este instructivo, se muestra cómo configurar una llamada a función para que la API de Gemini haga lo siguiente: interpretar las solicitudes de iluminación de los usuarios y asignarlas a la configuración de la API para controlar un el brillo de la luz y los valores de temperatura de color.

Antes de comenzar: Configura tu proyecto y clave de API

Antes de llamar a la API de Gemini, debes configurar tu proyecto tu clave de API.

Define una función de API

Crea una función que realice una solicitud a la API. Esta función debe definirse en el código de tu aplicación, pero podrían llamar a servicios o APIs fuera de tu aplicación. La API de Gemini no llama a esta función directamente, por lo que puedes controlar cómo y cuándo se ejecuta esta función a través de tu aplicación código. Para fines de demostración, este instructivo define una función de API simulada que solo devuelve los valores de iluminación solicitados:

def set_light_values(brightness, color_temp):
    """Set the brightness and color temperature of a room light. (mock API).

    Args:
        brightness: Light level from 0 to 100. Zero is off and 100 is full brightness
        color_temp: Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.

    Returns:
        A dictionary containing the set brightness and color temperature.
    """
    return {
        "brightness": brightness,
        "colorTemperature": color_temp
    }

Cuando creas una función para usarla en una llamada a función del modelo, debe incluir tantos detalles como sea posible en la función y el parámetro descripciones. El modelo generativo usa esta información para determinar función para seleccionar y cómo proporcionar valores para los parámetros en la función llamada.

Declara funciones durante la inicialización del modelo

Cuando quieras usar las llamadas a función con un modelo, debes declarar tu cuando inicializas el objeto del modelo. Para declarar las funciones, establece el parámetro tools del modelo:

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                              tools=[set_light_values])

Genera una llamada a función

Una vez que hayas inicializado el modelo con las declaraciones de tu función, puedes indicar al modelo con la función definida. Deberías usar las llamadas a funciones con las instrucciones de chat (sendMessage()), ya que las llamadas a función suelen beneficiarse de con el contexto de instrucciones y respuestas anteriores.

chat = model.start_chat()
response = chat.send_message('Dim the lights so the room feels cozy and warm.')
response.text

El SDK de Python ChatSession El objeto simplifica la administración de las sesiones de chat mediante el control del historial de conversaciones. por ti. Puedes usar enable_automatic_function_calling para tener el SDK automáticamente

# Create a chat session that automatically makes suggested function calls
chat = model.start_chat(enable_automatic_function_calling=True)

Llamadas a funciones paralelas

Además de las llamadas a funciones básicas descritas anteriormente, también puedes llamar a varias funciones en un solo turno. En esta sección, se muestra un ejemplo de cómo puedes usar las llamadas a funciones paralelas.

Definir las herramientas

def power_disco_ball(power: bool) -> bool:
    """Powers the spinning disco ball."""
    print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
    return True


def start_music(energetic: bool, loud: bool, bpm: int) -> str:
    """Play some music matching the specified parameters.

    Args:
      energetic: Whether the music is energetic or not.
      loud: Whether the music is loud or not.
      bpm: The beats per minute of the music.

    Returns: The name of the song being played.
    """
    print(f"Starting music! {energetic=} {loud=}, {bpm=}")
    return "Never gonna give you up."


def dim_lights(brightness: float) -> bool:
    """Dim the lights.

    Args:
      brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
    """
    print(f"Lights are now set to {brightness:.0%}")
    return True

Ahora llama al modelo con una instrucción que pueda usar todas las herramientas especificadas.

# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]

model = genai.GenerativeModel(model_name="gemini-1.5-flash", tools=house_fns)

# Call the API.
chat = model.start_chat()
response = chat.send_message("Turn this place into a party!")

# Print out each of the function calls requested from this single call.
for part in response.parts:
    if fn := part.function_call:
        args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
        print(f"{fn.name}({args})")
power_disco_ball(power=True)
start_music(energetic=True, loud=True, bpm=120.0)
dim_lights(brightness=0.3)

Cada uno de los resultados impresos refleja una única llamada a función que el modelo solicitó. Para devolver los resultados, incluye las respuestas en el mismo orden en que se solicitaron.

# Simulate the responses from the specified tools.
responses = {
    "power_disco_ball": True,
    "start_music": "Never gonna give you up.",
    "dim_lights": True,
}

# Build the response parts.
response_parts = [
    genai.protos.Part(function_response=genai.protos.FunctionResponse(name=fn, response={"result": val}))
    for fn, val in responses.items()
]

response = chat.send_message(response_parts)
print(response.text)
Let's get this party started! I've turned on the disco ball, started playing some upbeat music, and dimmed the lights. 🎶✨  Get ready to dance! 🕺💃

Asignación de tipos de datos de llamadas a función

La extracción automática de esquemas a partir de funciones de Python no funciona en todos los casos. Por ejemplo, no se abordan casos en los que describes los campos de un objeto de diccionario anidado, pero la API sí lo admite. La API puede describir cualquiera de los siguientes tipos:

AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType])

La biblioteca cliente google.ai.generativelanguage proporciona acceso a los tipos de bajo nivel, lo que te da control total.

Primero, un vistazo al atributo _tools del modelo, puedes ver cómo describe las funciones que le pasaste al modelo:

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                             tools=[multiply])

model._tools.to_proto()
[function_declarations {
   name: "multiply"
   description: "returns a * b."
   parameters {
     type_: OBJECT
     properties {
       key: "b"
       value {
         type_: NUMBER
       }
     }
     properties {
       key: "a"
       value {
         type_: NUMBER
       }
     }
     required: "a"
     required: "b"
   }
 }]

Muestra la lista de objetos genai.protos.Tool que se enviarían al en la API de Cloud. Si no te resulta familiar el formato impreso, es porque son productos de Google protobufs. Cada genai.protos.Tool (1 en este caso) contiene una lista de genai.protos.FunctionDeclarations, que describe una función y su argumentos.

Aquí hay una declaración para la misma función de multiplicación escrita con la genai.protos de clases. Ten en cuenta que estas clases solo describen la función para la API, no incluyen una implementación de ella. Por lo tanto, no funciona con las llamadas automáticas a funciones, pero las funciones no siempre necesitan un para implementarlos.

calculator = genai.protos.Tool(
    function_declarations=[
      genai.protos.FunctionDeclaration(
        name='multiply',
        description="Returns the product of two numbers.",
        parameters=genai.protos.Schema(
            type=genai.protos.Type.OBJECT,
            properties={
                'a':genai.protos.Schema(type=genai.protos.Type.NUMBER),
                'b':genai.protos.Schema(type=genai.protos.Type.NUMBER)
            },
            required=['a','b']
        )
      )
    ])

De manera equivalente, puedes describir esto como un objeto compatible con JSON:

calculator = {'function_declarations': [
      {'name': 'multiply',
       'description': 'Returns the product of two numbers.',
       'parameters': {'type_': 'OBJECT',
       'properties': {
         'a': {'type_': 'NUMBER'},
         'b': {'type_': 'NUMBER'} },
       'required': ['a', 'b']} }]}
genai.protos.Tool(calculator)
function_declarations {
  name: "multiply"
  description: "Returns the product of two numbers."
  parameters {
    type_: OBJECT
    properties {
      key: "b"
      value {
        type_: NUMBER
      }
    }
    properties {
      key: "a"
      value {
        type_: NUMBER
      }
    }
    required: "a"
    required: "b"
  }
}

De cualquier manera, pasas una representación de un genai.protos.Tool o una lista de herramientas a

model = genai.GenerativeModel('gemini-1.5-flash', tools=calculator)
chat = model.start_chat()

response = chat.send_message(
    f"What's 234551 X 325552 ?",
)

Al igual que antes, el modelo muestra un genai.protos.FunctionCall que invoca la función multiply de la calculadora:

response.candidates
[index: 0
content {
  parts {
    function_call {
      name: "multiply"
      args {
        fields {
          key: "b"
          value {
            number_value: 325552
          }
        }
        fields {
          key: "a"
          value {
            number_value: 234551
          }
        }
      }
    }
  }
  role: "model"
}
finish_reason: STOP
]

Ejecuta la función tú mismo:

fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'

result = fc.args['a'] * fc.args['b']
result
76358547152.0

Envía el resultado al modelo para continuar la conversación:

response = chat.send_message(
    genai.protos.Content(
    parts=[genai.protos.Part(
        function_response = genai.protos.FunctionResponse(
          name='multiply',
          response={'result': result}))]))