Ver en ai.google.dev | Ejecutar en Google Colab | Ver código fuente en GitHub |
Puedes proporcionar descripciones de funciones a los modelos de Gemini. El modelo puede pedirte que llames a una función y envíes el resultado para ayudar al modelo a manejar tu consulta.
Instalar
Instala el SDK de Python
El SDK de Python para la API de Gemini se encuentra en el paquete google-generativeai
. Instala la dependencia con pip:
pip install -U -q google-generativeai
Importa paquetes
Importa los paquetes necesarios.
import pathlib
import textwrap
import time
import google.generativeai as genai
from IPython import display
from IPython.display import Markdown
def to_markdown(text):
text = text.replace('•', ' *')
return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
Cómo configurar tu clave de API
Para poder usar la API de Gemini, primero debes obtener una clave de API. Si aún no tienes una, crea una con un clic en Google AI Studio.
En Colab, agrega la clave al administrador de Secrets en la "automated" del panel izquierdo. Asígnale el nombre API_KEY
.
Una vez que tengas la clave de API, pásala al SDK. Puedes hacerlo de dos maneras:
- Coloca la clave en la variable de entorno
GOOGLE_API_KEY
(el SDK la recogerá automáticamente desde allí). - Pasa la llave a
genai.configure(api_key=...)
try:
# Used to securely store your API key
from google.colab import userdata
# Or use `os.getenv('API_KEY')` to fetch an environment variable.
GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
except ImportError:
import os
GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']
genai.configure(api_key=GOOGLE_API_KEY)
Conceptos básicos de la función
Puedes pasar una lista de funciones al argumento tools
cuando creas un genai.GenerativeModel
.
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.0-pro',
tools=[multiply])
model
genai.GenerativeModel( model_name='models/gemini-1.0-pro', generation_config={}, safety_settings={}, tools=<google.generativeai.types.content_types.FunctionLibrary object at 0x10e73fe90>, )
La forma recomendada de usar la llamada a funciones es a través de la interfaz del chat. El motivo principal es que FunctionCalls
se adapta bien a la estructura de varios turnos del chat.
chat = model.start_chat(enable_automatic_function_calling=True)
Con la llamada automática a funciones habilitada, chat.send_message
llama automáticamente a tu función si el modelo lo solicita.
Parece que solo muestra una respuesta de texto que contiene la respuesta correcta:
response = chat.send_message('I have 57 cats, each owns 44 mittens, how many mittens is that in total?')
response.text
'The total number of mittens is 2508.'
57*44
2508
Si consultas en ChatSession.history
, puedes ver la secuencia de eventos:
- Enviaste la pregunta.
- El modelo respondió con
glm.FunctionCall
. genai.ChatSession
ejecutó la función de manera local y envió al modelo unglm.FunctionResponse
.- El modelo usó la salida de la función en su respuesta.
for content in chat.history:
part = content.parts[0]
print(content.role, "->", type(part).to_dict(part))
print('-'*80)
user -> {'text': 'I have 57 cats, each owns 44 mittens, how many mittens is that in total?'} -------------------------------------------------------------------------------- model -> {'function_call': {'name': 'multiply', 'args': {'a': 57.0, 'b': 44.0} } } -------------------------------------------------------------------------------- user -> {'function_response': {'name': 'multiply', 'response': {'result': 2508.0} } } -------------------------------------------------------------------------------- model -> {'text': 'The total number of mittens is 2508.'} --------------------------------------------------------------------------------
En general, el diagrama de estados es el siguiente:
El modelo puede responder con múltiples llamadas a función antes de mostrar una respuesta de texto, y las llamadas a funciones vienen antes de la respuesta de texto.
Aunque todo esto se controló automáticamente, si necesitas más control, puedes hacer lo siguiente:
- Deja el
enable_automatic_function_calling=False
predeterminado y procesa las respuestas de laglm.FunctionCall
por tu cuenta. - También puedes usar
GenerativeModel.generate_content
, donde también debes administrar el historial de chat.
[Opcional] Acceso de bajo nivel
La extracción automática del esquema de las funciones de Python no funciona en todos los casos. Por ejemplo: no se manejan 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 de google.ai.generativelanguage
proporciona acceso a los tipos de nivel inferior con el control total.
import google.ai.generativelanguage as glm
Primero, revisa el 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.0-pro',
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" } }]
Esto muestra la lista de objetos glm.Tool
que se enviarían a la API. Si el formato impreso no te resulta conocido, es porque estas son clases de protobuf de Google. Cada glm.Tool
(1 en este caso) contiene una lista de glm.FunctionDeclarations
, que describen una función y sus argumentos.
A continuación, se muestra una declaración para la misma función de multiplicación escrita con las clases glm
.
Ten en cuenta que estas clases solo describen la función para la API, no incluyen una implementación de ella. Por lo tanto, el uso de esto no funciona con las llamadas automáticas a funciones, pero las funciones no siempre necesitan una implementación.
calculator = glm.Tool(
function_declarations=[
glm.FunctionDeclaration(
name='multiply',
description="Returns the product of two numbers.",
parameters=glm.Schema(
type=glm.Type.OBJECT,
properties={
'a':glm.Schema(type=glm.Type.NUMBER),
'b':glm.Schema(type=glm.Type.NUMBER)
},
required=['a','b']
)
)
])
De forma equivalente, puedes describirlo 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']} }]}
glm.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 glm.Tool
o una lista de herramientas a
model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()
response = chat.send_message(
f"What's 234551 X 325552 ?",
)
Al igual que antes, el modelo muestra un glm.FunctionCall
invocando 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(
glm.Content(
parts=[glm.Part(
function_response = glm.FunctionResponse(
name='multiply',
response={'result': result}))]))
Resumen
El SDK admite llamadas a funciones básicas. Recuerda que es más fácil administrarlo con el modo chat debido a la estructura natural de ida y vuelta. Estás a cargo de llamar a las funciones y enviar los resultados al modelo para que pueda producir una respuesta de texto.