Zobacz na ai.google.dev | Uruchom w Google Colab | Wyświetl źródło na GitHubie |
Za pomocą wywołań funkcji możesz definiować funkcje niestandardowe i przekazywać je do Gemini. Model nie wywołuje bezpośrednio tych funkcji, ale generuje dane wyjściowe uporządkowanych danych, które określają nazwę funkcji i sugerowane argumenty. Dane wyjściowe umożliwiają wywoływanie zewnętrznych interfejsów API, a wynikowe dane z interfejsu API można później włączyć z powrotem do modelu, co pozwoli uzyskać bardziej kompleksowe odpowiedzi na zapytania. Wywoływanie funkcji umożliwia modelom LLM interakcję z informacjami w czasie rzeczywistym i różnymi usługami, takimi jak bazy danych, systemy zarządzania relacjami z klientami i repozytoria dokumentów, co zwiększa ich zdolność do udzielania trafnych i kontekstowych odpowiedzi. Modelom Gemini możesz podawać opisy funkcji. Model może poprosić Cię o wywołanie funkcji i odesłanie wyniku, aby model mógł lepiej obsłużyć zapytanie.
Więcej informacji znajdziesz w wprowadzeniu do wywoływania funkcji.
Konfiguracja
Zainstaluj pakiet SDK Pythona
Pakiet SDK Pythona dla interfejsu Gemini API znajduje się w pakiecie google-generativeai
. Zainstaluj zależność za pomocą narzędzia pip:
pip install -U -q google-generativeai
Importowanie pakietów
Zaimportuj niezbędne pakiety.
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))
Konfigurowanie klucza interfejsu API
Aby korzystać z interfejsu Gemini API, musisz najpierw uzyskać klucz interfejsu API. Jeśli nie masz jeszcze klucza, utwórz go jednym kliknięciem w Google AI Studio.
Uzyskiwanie klucza interfejsu API
W Colab dodaj klucz do menedżera obiektów tajnych w sekcji „🔑” w panelu po lewej stronie. Nadaj mu nazwę API_KEY
.
Przekaż klucz interfejsu API do pakietu SDK. Można to zrobić na dwa sposoby:
- Umieść klucz w zmiennej środowiskowej
GOOGLE_API_KEY
(pakiet SDK automatycznie go stamtąd zabierze). - Przekaż klucz do:
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)
Podstawy wywoływania funkcji
Aby używać wywoływania funkcji, podczas tworzenia elementu GenerativeModel
przekaż listę funkcji do parametru tools
. Model wykorzystuje nazwę funkcji, ciąg dokumentu, parametry i adnotacje typu parametru do określenia, czy potrzebuje funkcji do najlepszej odpowiedzi na pytanie.
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>, )
Zaleca się korzystanie z wywołań funkcyjnych przez interfejs czatu. Dzieje się tak, ponieważ wywołania funkcji w naturalny sposób pasują do czatów wieloetapowych, ponieważ rejestrują one interakcje między użytkownikiem a modelem. Interfejs ChatSession
pakietu Python SDK jest świetnym rozwiązaniem na potrzeby czatów, ponieważ obsługuje on historię rozmowy za Ciebie, a używanie parametru enable_automatic_function_calling
jeszcze bardziej upraszcza wywoływanie funkcji:
chat = model.start_chat(enable_automatic_function_calling=True)
Przy włączonym automatycznym wywoływaniu funkcji chat.send_message
automatycznie wywołuje Twoją funkcję, jeśli model o nie poprosi.
Wygląda na to, że zwracany jest komunikat zawierający poprawną odpowiedź:
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
Przejrzyj historię czatu, aby zobaczyć przebieg rozmowy i sposób integracji z nią wywołań funkcji.
Właściwość ChatSession.history
przechowuje chronologiczny rekord rozmowy między użytkownikiem a modelem Gemini. Każdy ruch w wątku jest reprezentowany przez obiekt glm.Content
, który zawiera te informacje:
- Rola: wskazuje, czy treści pochodzą od „użytkownika” czy „modelu”.
- Części: lista obiektów
glm.Part
, które reprezentują poszczególne komponenty wiadomości. W przypadku modelu tylko tekstowego te części mogą obejmować:- Tekst: zwykły tekst.
- Wywołanie funkcji (
glm.FunctionCall
): żądanie z modelu o wykonanie określonej funkcji z podanymi argumentami. - Odpowiedź funkcji (
glm.FunctionResponse
): wynik zwrócony przez użytkownika po wykonaniu żądanej funkcji.
W poprzednim przykładzie z obliczaniem rękawiczek w historii występuje taka sekwencja:
- Użytkownik: zadaje pytanie o łączną liczbę rękawiczek.
- Model: określa, że funkcja mnożenia jest pomocna, i wysyła do użytkownika żądanie FunctionCall.
- Użytkownik:
ChatSession
automatycznie wykonuje funkcję (ze względu na ustawienie parametruenable_automatic_function_calling
) i zwracaFunctionResponse
z obliczonym wynikiem. - Model: wykorzystuje dane wyjściowe funkcji do sformułowania ostatecznej odpowiedzi i przedstawia ją jako odpowiedź tekstową.
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.'} --------------------------------------------------------------------------------
Ogólnie diagram stanu wygląda tak:
Przed zwróceniem odpowiedzi tekstowej model może odpowiedzieć za pomocą wielu wywołań funkcji, a wywołania funkcji mają miejsce przed odpowiedzią tekstową.
Wszystko odbywało się automatycznie, ale jeśli chcesz mieć większą kontrolę, możesz:
- Pozostaw domyślną wartość
enable_automatic_function_calling=False
i samodzielnie przetwarzaj odpowiedziglm.FunctionCall
. - Możesz też użyć aplikacji
GenerativeModel.generate_content
, gdzie musisz również zarządzać historią czatu.
Wywoływanie funkcji równoległej
Oprócz opisanych powyżej wywołań podstawowych funkcji możesz też wywoływać wiele funkcji w jednym kroku. W tej sekcji znajdziesz przykład użycia równoległego wywoływania funkcji.
Zdefiniuj narzędzia.
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
Teraz wywołaj model z instrukcją, która może korzystać ze wszystkich określonych narzędzi.
# 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)
Każdy drukowany wynik odzwierciedla jedno wywołanie funkcji, którego zażądał model. Aby odesłać wyniki, wpisz odpowiedzi w takiej kolejności, w jakiej były wymagane.
# 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! 🕺💃
(Opcjonalnie) Dostęp niskiego poziomu
Automatyczne wyodrębnianie schematu z funkcji Pythona nie we wszystkich przypadkach działa. Na przykład: nie obsługuje przypadków, gdy opisujesz pola zagnieżdżonego obiektu słownika, ale interfejs API to umożliwia. Interfejs API może opisywać każdy z tych typów:
AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]
Biblioteka klienta google.ai.generativelanguage
zapewnia dostęp do typów niskiego poziomu, co daje Ci pełną kontrolę.
import google.ai.generativelanguage as glm
Najpierw rzut oka na atrybut _tools
modelu możesz zobaczyć, jak opisuje on funkcje przekazane do modelu:
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" } }]
Zwraca listę obiektów glm.Tool
, które zostałyby wysłane do interfejsu API. Jeśli nie znasz formatu drukowanego, oznacza to, że są to klasy protokołu Google. Każdy element glm.Tool
(w tym przypadku 1) zawiera listę obiektów glm.FunctionDeclarations
, która opisuje funkcję i jej argumenty.
Oto deklaracja dla tej samej funkcji mnożenia zapisanej za pomocą klas glm
.
Pamiętaj, że te klasy opisują tylko funkcję interfejsu API, a nie zawierają jego implementacji. Używanie tej metody nie działa w przypadku automatycznego wywoływania funkcji, ale funkcje nie zawsze wymagają implementacji.
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']
)
)
])
Możesz go również opisać jako obiekt zgodny z formatem 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" } }
W obu przypadkach przekazujesz reprezentację obiektu glm.Tool
lub listy narzędzi do
model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()
response = chat.send_message(
f"What's 234551 X 325552 ?",
)
Podobnie jak przed zwróceniem funkcji glm.FunctionCall
, która wywołuje funkcję multiply
kalkulatora:
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 ]
Wykonaj funkcję samodzielnie:
fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'
result = fc.args['a'] * fc.args['b']
result
76358547152.0
Aby kontynuować rozmowę, wyślij wynik do modelu:
response = chat.send_message(
glm.Content(
parts=[glm.Part(
function_response = glm.FunctionResponse(
name='multiply',
response={'result': result}))]))
Podsumowanie
Pakiet SDK obsługuje podstawowe wywoływanie funkcji. Pamiętaj, że łatwiej jest nim zarządzać w trybie czatu dzięki naturalnej strukturze przechodzenia z powrotem i z powrotem. To Ty odpowiadasz za wywoływanie funkcji i wysyłanie wyników z powrotem do modelu, aby mógł wygenerować odpowiedź tekstową.