Auf ai.google.dev ansehen | In Google Colab ausführen | Quelle auf GitHub ansehen |
Verwenden Sie Funktionsaufrufe, um benutzerdefinierte Funktionen zu definieren und an Gemini zu übergeben. Das Modell ruft diese Funktionen nicht direkt auf, sondern generiert eine strukturierte Datenausgabe, die den Funktionsnamen und vorgeschlagene Argumente angibt. Diese Ausgabe ermöglicht das Aufrufen externer APIs. Die resultierende API-Ausgabe kann dann wieder in das Modell integriert werden, was umfassendere Abfrageantworten ermöglicht. Durch Funktionsaufrufe können LLMs mit Echtzeitinformationen und verschiedenen Diensten wie Datenbanken, Customer-Relationship-Management-Systemen und Dokumenten-Repositories interagieren und so relevante und kontextabhängige Antworten bereitstellen. Sie können Gemini-Modelle mit Funktionsbeschreibungen bereitstellen. Möglicherweise fordert das Modell Sie auf, eine Funktion aufzurufen und das Ergebnis zurückzusenden, um das Modell bei der Verarbeitung Ihrer Abfrage zu unterstützen.
Weitere Informationen finden Sie unter Einführung in Funktionsaufrufe.
Einrichtung
Python SDK installieren
Das Python SDK für die Gemini API ist im Paket google-generativeai
enthalten. Installieren Sie die Abhängigkeit mit „Pip“:
pip install -U -q google-generativeai
Pakete importieren
Importieren Sie die erforderlichen Pakete.
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))
API-Schlüssel einrichten
Bevor Sie die Gemini API verwenden können, müssen Sie zuerst einen API-Schlüssel abrufen. Falls Sie noch keinen Schlüssel haben, können Sie mit einem Klick in Google AI Studio einen Schlüssel erstellen.
Fügen Sie den Schlüssel in Colab im linken Bereich unter „🚀“ zum Secret-Manager hinzu. Geben Sie ihr den Namen API_KEY
.
Sobald Sie den API-Schlüssel haben, übergeben Sie ihn an das SDK. Dafür haben Sie die beiden folgenden Möglichkeiten:
- Fügen Sie den Schlüssel in die Umgebungsvariable
GOOGLE_API_KEY
ein. Das SDK übernimmt ihn dort automatisch. - Schlüssel an
genai.configure(api_key=...)
übergeben
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)
Grundlagen des Funktionsaufrufs
Wenn Sie Funktionsaufrufe verwenden möchten, übergeben Sie beim Erstellen einer GenerativeModel
eine Liste von Funktionen an den Parameter tools
. Das Modell verwendet den Funktionsnamen, den docstring, die Parameter und die Annotationen des Parametertyps, um zu entscheiden, ob die Funktion am besten auf eine Aufforderung antworten muss.
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>, )
Es wird empfohlen, Funktionsaufrufe über die Chat-Oberfläche zu verwenden. Das liegt daran, dass Funktionsaufrufe automatisch in Multi-Turn-Chats passen, da sie die Hin- und Her-Interaktion zwischen Nutzer und Modell erfassen. Das Python SDK ChatSession
ist eine hervorragende Schnittstelle für Chats, da es den Unterhaltungsverlauf für Sie verwaltet und die Verwendung des Parameters enable_automatic_function_calling
den Funktionsaufruf noch weiter vereinfacht:
chat = model.start_chat(enable_automatic_function_calling=True)
Wenn automatische Funktionsaufrufe aktiviert sind, ruft chat.send_message
die Funktion automatisch auf, wenn das Modell dies anfordert.
Es scheint einfach eine Textantwort zurückzugeben, die die richtige Antwort enthält:
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
Sehen Sie sich das Chat-Protokoll an, um den Ablauf der Unterhaltung und die Integration von Funktionsaufrufen zu sehen.
In der Property ChatSession.history
wird ein chronologischer Datensatz der Unterhaltung zwischen dem Nutzer und dem Gemini-Modell gespeichert. Jede Runde in der Unterhaltung wird durch ein glm.Content
-Objekt dargestellt, das die folgenden Informationen enthält:
- Rolle: Gibt an, ob der Inhalt vom „Nutzer“ oder dem „Modell“ stammt.
- Parts (Teile): Eine Liste von
glm.Part
-Objekten, die einzelne Komponenten der Nachricht darstellen. Bei einem reinen Textmodell können diese Teile so aussehen:- Text: Nur Textnachrichten.
- Funktionsaufruf (
glm.FunctionCall
): Eine Anfrage vom Modell zur Ausführung einer bestimmten Funktion mit angegebenen Argumenten. - Funktionsantwort (
glm.FunctionResponse
): Das Ergebnis, das vom Nutzer nach Ausführung der angeforderten Funktion zurückgegeben wird.
Im vorherigen Beispiel mit der Berechnung der Fäustlinge zeigt der Verlauf die folgende Reihenfolge:
- Nutzer: Stellt die Frage zur Gesamtzahl der Fausthandschuhe.
- Modell: Bestimmt, dass die Multiplikationsfunktion hilfreich ist, und sendet eine „FunctionCall“-Anfrage an den Nutzer.
- Nutzer:
ChatSession
führt die Funktion automatisch aus, weilenable_automatic_function_calling
festgelegt wurde, und sendet eineFunctionResponse
mit dem berechneten Ergebnis zurück. - Modell: Verwendet die Ausgabe der Funktion, um die endgültige Antwort zu formulieren und als Textantwort zu präsentieren.
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.'} --------------------------------------------------------------------------------
Im Allgemeinen sieht das Zustandsdiagramm so aus:
Das Modell kann mit mehreren Funktionsaufrufen antworten, bevor eine Textantwort zurückgegeben wird, und Funktionsaufrufe vor der Textantwort.
Dies wurde zwar automatisch abgewickelt, aber wenn Sie mehr Kontrolle benötigen, haben Sie folgende Möglichkeiten:
- Behalten Sie den standardmäßigen
enable_automatic_function_calling=False
bei und verarbeiten Sie dieglm.FunctionCall
-Antworten selbst. - Alternativ können Sie
GenerativeModel.generate_content
verwenden. Dort müssen Sie auch das Chatprotokoll verwalten.
Parallele Funktionsaufrufe
Neben den oben beschriebenen grundlegenden Funktionsaufrufen können Sie auch mehrere Funktionen in einer einzigen Abfolge aufrufen. Dieser Abschnitt enthält ein Beispiel dafür, wie Sie parallele Funktionsaufrufe verwenden können.
Tools definieren
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
Rufen Sie nun das Modell mit einer Anweisung auf, die alle angegebenen Tools verwenden könnte.
# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]
model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest", 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)
Jedes der gedruckten Ergebnisse steht für einen einzelnen Funktionsaufruf, den das Modell angefordert hat. Wenn Sie die Ergebnisse zurücksenden möchten, geben Sie die Antworten in der Reihenfolge an, in der sie angefordert wurden.
# 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 = [
glm.Part(function_response=glm.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! 🕺💃
Optional: Low-Level-Zugriff
Die automatische Extraktion des Schemas aus Python-Funktionen funktioniert nicht in allen Fällen. Beispiel: Sie ist nicht für Fälle geeignet, in denen Sie die Felder eines verschachtelten Wörterbuchobjekts beschreiben, aber die API unterstützt dies. Die API kann folgende Typen beschreiben:
AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]
Die google.ai.generativelanguage
-Clientbibliothek bietet Zugriff auf die untergeordneten Typen, sodass Sie vollständige Kontrolle haben.
import google.ai.generativelanguage as glm
Werfen Sie zuerst einen Blick auf das Attribut _tools
des Modells. Hier sehen Sie, wie es die Funktion(en) beschreibt, die Sie an das Modell übergeben haben:
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" } }]
Dadurch wird die Liste der glm.Tool
-Objekte zurückgegeben, die an die API gesendet werden würden. Wenn das gedruckte Format nicht vertraut ist, liegt das daran, dass dies die protobuf-Klassen von Google sind. Jedes glm.Tool
(in diesem Fall 1) enthält eine Liste von glm.FunctionDeclarations
, die eine Funktion und ihre Argumente beschreiben.
Hier ist eine Deklaration für dieselbe Multiplikationsfunktion, die mithilfe der glm
-Klassen geschrieben wurde.
Beachten Sie, dass diese Klassen nur die Funktion für das API beschreiben, sie keine Implementierung davon enthalten. Die Verwendung dieser Methode funktioniert also nicht mit automatischen Funktionsaufrufen, Funktionen erfordern jedoch nicht immer eine Implementierung.
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']
)
)
])
Entsprechend können Sie dies auch als JSON-kompatibles Objekt beschreiben:
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" } }
In beiden Fällen übergeben Sie eine Darstellung von glm.Tool
oder eine Liste von Tools an
model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()
response = chat.send_message(
f"What's 234551 X 325552 ?",
)
Wie zuvor, gibt das Modell einen glm.FunctionCall
zurück, der die multiply
-Funktion des Rechners aufruft:
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 ]
Führen Sie die Funktion selbst aus:
fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'
result = fc.args['a'] * fc.args['b']
result
76358547152.0
Senden Sie das Ergebnis an das Modell, um die Unterhaltung fortzusetzen:
response = chat.send_message(
glm.Content(
parts=[glm.Part(
function_response = glm.FunctionResponse(
name='multiply',
response={'result': result}))]))
Zusammenfassung
Im SDK werden grundlegende Funktionsaufrufe unterstützt. Denken Sie daran, dass der Chat-Modus aufgrund der natürlichen Hin- und Her-Struktur einfacher zu verwalten ist. Sie sind dafür verantwortlich, die Funktionen aufzurufen und Ergebnisse zurück an das Modell zu senden, damit es eine Textantwort erzeugen kann.