Jak korzystać z interfejsów API za pomocą wywołań funkcji w Gemini

1. Przegląd

Czym jest wywoływanie funkcji w Gemini?

Vertex AI Gemini API to rodzina modeli generatywnej AI opracowanych przez Google DeepMind, które są przeznaczone do zastosowań multimodalnych. Wywoływanie funkcji to funkcja modeli Gemini, która ułatwia programistom uzyskiwanie uporządkowanych danych wyjściowych z modeli generatywnych.

Deweloperzy mogą następnie używać tych danych wyjściowych do wywoływania innych interfejsów API i przekazywania odpowiednich danych odpowiedzi do modelu. Innymi słowy, wywoływanie funkcji pomaga łączyć modele generatywne z systemami zewnętrznymi, dzięki czemu generowane treści zawierają najbardziej aktualne i dokładne informacje.

Jak działa wywoływanie funkcji

Funkcje są opisywane za pomocą deklaracji funkcji, co pomaga modelowi generatywnemu zrozumieć przeznaczenie i parametry funkcji. Gdy w zapytaniu przekażesz do modelu generatywnego deklaracje funkcji, model zwróci obiekt strukturalny, który zawiera nazwy odpowiednich funkcji i ich argumenty na podstawie zapytania użytkownika. Pamiętaj, że w przypadku wywoływania funkcji model nie wywołuje jej w rzeczywistości. Zamiast tego możesz użyć zwróconej funkcji i parametrów, aby wywołać funkcję w dowolnym języku, bibliotece lub frameworku.

Interfejs API

Co utworzysz

W ramach tego ćwiczenia w Codelabs utworzysz potok generatywnej AI za pomocą Gemini API w Vertex AI i Pythona. Użytkownicy mogą zadawać pytania o kursy wymiany walut, a system pobiera najnowsze dane z zewnętrznego interfejsu API i odpowiada na pytania użytkowników.

Czego się nauczysz

  • Jak wchodzić w interakcję z modelem Gemini za pomocą biblioteki klienta w Pythonie
  • Jak zdefiniować deklarację funkcji i zarejestrować ją jako narzędzie
  • Jak wywołać Gemini i uzyskać odpowiedź z wywołania funkcji
  • Jak przekazać odpowiedź funkcji do Gemini i odpowiedzieć użytkownikowi

Czego potrzebujesz

2. Konfiguracja i wymagania

Zanim zaczniesz korzystać z wywoływania funkcji w Gemini, musisz włączyć interfejs Vertex AI API i zainstalować najnowszą wersję biblioteki klienta Vertex AI Python.

Włącz Vertex AI API

Aby włączyć interfejs Vertex AI API, wykonaj te czynności:

  1. W przeglądarce otwórz stronę szczegółów usługi Vertex AI API.
  2. Kliknij przycisk Włącz, aby włączyć Vertex AI API w projekcie Google Cloud.

Instalowanie biblioteki klienta Python dla Vertex AI

Aby zainstalować biblioteki klienta w Pythonie dla Vertex AI, wykonaj te czynności:

  1. Otwórz terminal w środowisku programistycznym.
  2. Sprawdź, czy masz prawidłowe środowisko programistyczne w Pythonie, a w razie potrzeby zapoznaj się z tymi wytycznymi.
  3. Aby zainstalować bibliotekę klienta Python dla Vertex AI, uruchom to polecenie:
    pip install --upgrade google-cloud-aiplatform
    
  4. Jeśli pracujesz w środowisku notatnika, może być konieczne ponowne uruchomienie środowiska wykonawczego lub jądra, aby używać nowo zainstalowanych pakietów.

Teraz możesz używać interfejsu Vertex AI API.

3. Zrozumienie problemu

Czy zdarzyło Ci się kiedyś zadać dużemu modelowi językowemu lub modelowi generatywnej AI pytanie o informacje w czasie rzeczywistym lub aktualne, a w odpowiedzi otrzymać nieaktualne lub niedokładne informacje?

Spróbujmy! Najpierw zaimportujemy odpowiednie pakiety Pythona i zainicjujemy model Gemini. Poniższy kod możesz uruchomić w środowisku programistycznym w języku Python, takim jak Colab lub Colab Enterprise, po zainstalowaniu najnowszej wersji pakietu Vertex AI SDK for Python:

import vertexai
from vertexai.generative_models import GenerativeModel
model = GenerativeModel("gemini-1.5-pro-001")

Teraz zadajmy pytanie o dzisiejszy kurs wymiany różnych walut:

response = model.generate_content(
    "What's the exchange rate for euros to dollars today?"
)
print(response.text)

Model powinien wygenerować ograniczoną lub nieaktualną odpowiedź podobną do tej:

As an AI language model, I don't have access to real-time currency exchange
rates. However, as of my last update in September 2021, the approximate exchange
rate between euros (EUR) and US dollars (USD) was:

1 EUR ≈ 1.18 USD

Please note that currency exchange rates constantly fluctuate and can vary
depending on various factors such as economic conditions, supply and demand,
political events, and more. To obtain the most up-to-date and accurate exchange
rate, I recommend using a reliable currency converter or financial website that
provides live rates.

[...]

Jeśli użytkownik otrzyma taką odpowiedź, będzie musiał zmienić kontekst, aby wyszukać waluty, które go interesują, pobrać najnowszy kurs wymiany i samodzielnie dokonać konwersji.

W idealnym przypadku potok modelu generatywnego mógłby wykonywać niektóre lub wszystkie z tych zadań za użytkownika. W następnej sekcji wypróbujesz kilka typowych obejść, które pozwolą Ci uzyskiwać od modeli generatywnych odpowiedzi w formacie strukturalnym, aby móc wywoływać systemy zewnętrzne.

4. Wypróbuj typowe obejścia

Podczas pracy z modelami generatywnymi w sytuacjach, w których potrzebujesz aktualnych informacji lub danych ze źródeł zewnętrznych, możesz wywołać zewnętrzny interfejs API, a następnie przekazać wyniki z powrotem do modelu generatywnego, aby mógł ich użyć w swojej odpowiedzi.

Zanim wywołasz system zewnętrzny, musisz określić odpowiednią funkcję, wyodrębnić od użytkownika odpowiednie parametry i umieścić je w obiekcie danych strukturalnych. Zazwyczaj wymaga to wyczerpującego inżynierowania promptów, aby zmusić model generatywny do wygenerowania prawidłowych danych strukturalnych.

Wróćmy do pytania, które zadaliśmy w poprzedniej sekcji, i dodajmy do niego kilka dodatkowych instrukcji dla modelu. Wyślij do modelu Gemini to żądanie:

user_prompt = "What's the exchange rate from euros to US dollars today?"

response = model.generate_content("""
Your task is to extract parameters from the user's input and return it as a
structured JSON payload. The user will ask about the exchange rate and which
currency they are converting from and converting to.

User input: {user_prompt}

Please extract the currencies as parameters and put them in a JSON object.
""".format(user_prompt=user_prompt))
print(response.text)

W rezultacie otrzymujemy następującą odpowiedź tekstową, która nie jest prawidłowym kodem JSON i utrudnia nam pracę:

```json
{
  "currency_from": "euros",
  "currency_to": "US dollars"
}
```

W szczególności pierwszy i ostatni wiersz odpowiedzi tekstowej zawierają znaki ` ograniczające blok kodu, pierwszy wiersz zawiera specyfikator języka, a wartości w obiekcie JSON nie są standardowymi trzyliterowymi skrótami walut, których interfejs API wymiany walut oczekuje jako parametrów wejściowych.

Możemy spróbować użyć Pythona, aby przetworzyć ten tekst na prawidłowy kod JSON i słownik, dodać więcej instrukcji do promptu, podać 1 lub więcej przykładów oczekiwanych wyników, dostroić model lub wykonać kolejne wywołanie modelu generatywnego z prośbą o oczyszczenie kodu JSON.

Istnieje jednak bardziej deterministyczny sposób. Dowiedz się, jak używać wywoływania funkcji w Gemini, aby wysyłać zapytania o informacje w usługach zewnętrznych i zwracać trafne odpowiedzi użytkownikom.

5. Jak działa wywoływanie funkcji

Zanim zaczniemy wyodrębniać parametry i wywoływać funkcje, przyjrzyjmy się kolejnym etapom wywoływania funkcji i komponentom używanym w czasie działania.

Omówienie wywoływania funkcji w Gemini

Dane wejściowe użytkownika w interfejsie Gemini API

Prompt użytkownika jest wysyłany do interfejsu Gemini API, a w tym wywołaniu interfejsu API do modelu Gemini programista zdefiniował w narzędziu co najmniej jedną deklarację funkcji, aby model Gemini wiedział, które funkcje może wywołać i jak to zrobić.

Gemini API zwraca wywołanie funkcji

Na podstawie treści danych wejściowych i promptu użytkownika Gemini zwróci odpowiedź Function Call z danymi strukturalnymi, które zawierają nazwę funkcji do wywołania i odpowiednie parametry do użycia.

Wysyłanie żądania do interfejsu API

Następnie użyjesz nazwy funkcji i parametrów, aby wysłać żądanie do interfejsu API i pobrać informacje z systemu zewnętrznego lub interfejsu API. To żądanie do interfejsu API i odpowiedź są implementowane przez dewelopera w kodzie aplikacji i nie wchodzą w zakres interfejsu API i pakietu SDK Gemini. Możesz na przykład użyć biblioteki requests w języku Python, aby wywołać interfejs API REST i otrzymać odpowiedź w formacie JSON. Możesz też wywołać funkcję, korzystając z wybranej metody i biblioteki klienta.

Przekazywanie odpowiedzi interfejsu API do Gemini

Na koniec przekażesz odpowiedź interfejsu API z powrotem do modelu Gemini, aby mógł on wygenerować odpowiedź na początkowy prompt użytkownika lub wywołać inną odpowiedź wywołania funkcji, jeśli uzna, że potrzebuje dodatkowych informacji.

6. Wybierz interfejs API

Teraz gdy znasz już ogólny przepływ i poszczególne etapy wywoływania funkcji, możesz utworzyć potok generatywnej AI, który będzie pobierać najnowsze kursy wymiany walut. Najpierw musimy wybrać interfejs API, którego chcemy użyć jako źródła informacji.

W przypadku naszej aplikacji do wymiany walut użyjemy interfejsu API REST pod adresem https://www.frankfurter.app/, aby pobrać najnowsze informacje o globalnych kursach wymiany.

Aby korzystać z tego interfejsu API REST, możemy wywołać interfejs API REST za pomocą requests w Pythonie w ten sposób:

import requests
url = "https://api.frankfurter.app/latest"
response = requests.get(url)
response.text

lub prośbę cURL, np.:

curl https://api.frankfurter.app/latest

które zwraca odpowiedź podobną do tej:

{
  "amount": 1,
  "base": "EUR",
  "date": "2023-12-20",
  "rates": {
    "AUD": 1.6186, "BGN": 1.9558, "BRL": 5.3287,
    "CAD": 1.4609, "CHF": 0.946, "CNY": 7.8121,
    "CZK": 24.538, "DKK": 7.4565, "GBP": 0.86555,
    "HKD": 8.5439, "HUF": 385.23, "IDR": 16994,
    "ILS": 3.9983, "INR": 91.06, "ISK": 150.3,
    "JPY": 157.12, "KRW": 1425.62, "MXN": 18.6867,
    "MYR": 5.0977, "NOK": 11.2895, "NZD": 1.7421,
    "PHP": 60.991, "PLN": 4.3413, "RON": 4.9699,
    "SEK": 11.129, "SGD": 1.4562, "THB": 38.252,
    "TRY": 31.883, "USD": 1.0944, "ZAR": 20.111
  }
}

Funkcja wywoływania funkcji w Gemini nie wykonuje za Ciebie wywołania zewnętrznego interfejsu API, więc nie ma ograniczeń co do rodzaju interfejsu API, którego używasz. Możesz użyć usługi Cloud Run, funkcji w Cloud Functions, żądania do interfejsu API do usługi Google Cloud lub dowolnego zewnętrznego interfejsu API (typu) REST.

7. Zdefiniuj funkcję i narzędzie

Po wybraniu interfejsu API REST możemy zdefiniować specyfikację interfejsu API i zarejestrować funkcję w narzędziu.

Sprawdź, czy masz zainstalowaną najnowszą wersję pakietu SDK Vertex AI dla Pythona.

Następnie zaimportuj niezbędne moduły z pakietu SDK Pythona i zainicjuj model Gemini:

from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerativeModel,
    Part,
    Tool,
)

model = GenerativeModel("gemini-1.5-pro-001")

Wracając do interfejsu API REST na stronie https://api.frankfurter.app/, widzimy, że akceptuje on te parametry wejściowe:

Parametr

Typ

Opis

from

Ciąg znaków

Waluta, z której chcesz przeliczyć środki

to

Ciąg znaków

Waluta, na którą chcesz przeliczyć środki

date

Ciąg znaków

Data, dla której ma zostać pobrany kurs wymiany

Korzystając z tych parametrów, częściowa specyfikacja OpenAPI dla tego interfejsu API typu REST w formacie YAML wygląda tak:

openapi: 3.0.0
info:
  title: Frankfurter Exchange Rate API
  description: This API provides current and historical exchange rates
  version: 1.0.0
servers:
  - url: https://api.frankfurter.app
paths:
  /{date}:
    get:
      summary: Get the latest currency exchange rates.
      parameters:
        - name: date
          in: path
          description: Get currency rates for a specific date or 'latest' if a date is not specified
          required: true
          schema:
            type: string
        - name: from
          in: query
          description: The currency to convert from.
          required: true
          schema:
            type: string
        - name: to
          in: query
          description: The currency to convert to.
          schema:
            type: string

Teraz zarejestrujmy go jako FunctionDeclaration za pomocą pakietu SDK Pythona dla Gemini:

get_exchange_rate_func = FunctionDeclaration(
    name="get_exchange_rate",
    description="Get the exchange rate for currencies between countries",
    parameters={
    "type": "object",
    "properties": {
        "currency_date": {
            "type": "string",
            "description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
        },
        "currency_from": {
            "type": "string",
            "description": "The currency to convert from in ISO 4217 format"
        },
        "currency_to": {
            "type": "string",
            "description": "The currency to convert to in ISO 4217 format"
        }
    },
         "required": [
            "currency_from",
            "currency_date",
      ]
  },
)

W opisach funkcji i parametrów podaj jak najwięcej szczegółów, ponieważ model generatywny będzie używać tych informacji do określania, którą funkcję wybrać i jak wypełnić parametry w wywołaniu funkcji.

Na koniec zdefiniujesz Tool, który zawiera deklarację funkcji:

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

W tym przypadku w narzędziu używasz jednej deklaracji funkcji, ale pamiętaj, że możesz zarejestrować w nim co najmniej jedną deklarację funkcji, a model wybierze odpowiednią funkcję do użycia w czasie działania. Więcej informacji o klasach FunctionDeclaration, Tool i powiązanych klasach w pakiecie Gemini SDK for Python znajdziesz w dokumentacji Wywoływanie funkcji w interfejsie Gemini API.

Konfigurowanie definicji funkcji i narzędzi zostało zakończone. W następnej sekcji wywołamy model generatywny za pomocą tego narzędzia i uzyskamy wywołanie funkcji, którego możemy użyć do wywołania interfejsu API REST.

8. Generowanie wywołania funkcji

Teraz możesz wywołać model generatywny i uwzględnić zdefiniowany przez siebie symbol tool:

prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""

response = model.generate_content(
    prompt,
    tools=[exchange_rate_tool],
)

Przyjrzyjmy się obiektowi odpowiedzi:

print(response.candidates[0].content)

role: "model"
parts {
  function_call {
    name: "get_exchange_rate"
    args {
      fields {
        key: "currency_to"
        value {
          string_value: "SEK"
        }
      }
      fields {
        key: "currency_from"
        value {
          string_value: "AUD"
        }
      }
      fields {
        key: "currency_date"
        value {
          string_value: "latest"
        }
      }
    }
  }
}

Wygląda na to, że model wybrał jedną dostępną funkcję i zwrócił wywołanie funkcji get_exchange_rate wraz z parametrami. Parametry są w odpowiednim formacie. Gratulacje za uzyskanie ustrukturyzowanych odpowiedzi z modeli generatywnych.

W następnej sekcji użyjesz informacji z odpowiedzi do wysłania żądania do interfejsu API.

9. Wysyłanie żądania do interfejsu API

Pamiętaj, że wywoływanie funkcji w Gemini nie powoduje wywołania zewnętrznego interfejsu API. Możesz używać dowolnego języka, biblioteki lub platformy.

Do wywołania interfejsu REST API kursu wymiany walut użyjesz biblioteki requests w Pythonie.

Rozpakujmy odpowiedź do słownika Pythona:

params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
    params[key[9:]] = value
params

Teraz możemy zadzwonić pod numer requests lub skorzystać z innej metody:

import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text

W odpowiedzi otrzymasz mniej więcej takie dane:

'{"amount":1.0,"base":"AUD","date":"2024-01-16","rates":{"SEK":6.8682}}'

Otrzymaliśmy odpowiedź z interfejsu REST API z najnowszymi informacjami o kursie wymiany z dzisiaj. W następnej sekcji przekażemy te informacje z powrotem do modelu, aby mógł on wygenerować odpowiednią odpowiedź dla użytkownika.

10. Generowanie odpowiedzi

Na koniec wygenerujmy odpowiedź dla użytkownika, przekazując odpowiedź funkcji do modelu w kolejnej turze rozmowy:

response = model.generate_content(
    [
    Content(role="user", parts=[
        Part.from_text(prompt + """Give your answer in steps with lots of detail
            and context, including the exchange rate and date."""),
    ]),
    Content(role="function", parts=[
        Part.from_dict({
            "function_call": {
                "name": "get_exchange_rate",
            }
        })
    ]),
    Content(role="function", parts=[
        Part.from_function_response(
            name="get_exchange_rate",
            response={
                "content": api_response.text,
            }
        )
    ]),
    ],
    tools=[exchange_rate_tool],
)


response.candidates[0].content.parts[0].text

Gdy przekażemy odpowiedź funkcji z powrotem do modelu, odpowie on na prompt użytkownika, podając odpowiednie informacje z odpowiedzi interfejsu API.

The exchange rate from Australian dollars to Swedish krona on January 16, 2024,
is 1 Australian dollar is equal to 6.8663 Swedish krona.

So, 500 Australian dollars would be worth 500 * 6.8663 = 3,433.15 Swedish krona.

11. Wyświetl pełny przykład kodu

Na tym etapie możesz umieścić kod Pythona w interfejsie API backendu, korzystając z usługi Cloud Run, funkcji Cloud Functions lub innej usługi Cloud, i wdrożyć aplikację frontendową, która używa tego interfejsu API backendu do wykonywania zapytań o model i wywołań interfejsu API.

Oto pełny przykład kodu naszego ostatecznego rozwiązania:

import requests
from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerativeModel,
    Part,
    Tool,
)

model = GenerativeModel("gemini-1.5-pro-001")

get_exchange_rate_func = FunctionDeclaration(
    name="get_exchange_rate",
    description="Get the exchange rate for currencies between countries",
    parameters={
    "type": "object",
    "properties": {
        "currency_date": {
            "type": "string",
            "description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
        },
        "currency_from": {
            "type": "string",
            "description": "The currency to convert from in ISO 4217 format"
        },
        "currency_to": {
            "type": "string",
            "description": "The currency to convert to in ISO 4217 format"
        }
    },
         "required": [
            "currency_from",
            "currency_date",
      ]
  },
)

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""

response = model.generate_content(
    prompt,
    tools=[exchange_rate_tool],
)

response.candidates[0].content

params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
    params[key[9:]] = value
params

import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text

response = model.generate_content(
    [
    Content(role="user", parts=[
        Part.from_text(prompt + """Give your answer in steps with lots of detail
            and context, including the exchange rate and date."""),
    ]),
    Content(role="function", parts=[
        Part.from_dict({
            "function_call": {
                "name": "get_exchange_rate",
            }
        })
    ]),
    Content(role="function", parts=[
        Part.from_function_response(
            name="get_exchange_rate",
            response={
                "content": api_response.text,
            }
        )
    ]),
    ],
    tools=[exchange_rate_tool],
)


response.candidates[0].content.parts[0].text

W tej implementacji użyliśmy 2 żądań do modelu generatywnego: jednego do wygenerowania wywołania funkcji i drugiego do zwrócenia odpowiedzi funkcji. Pamiętaj, że to tylko jedna z metod obsługi wywołań funkcji i odpowiedzi na nie w Gemini. Możesz też wykonać dodatkowe wywołania funkcji, aby uzyskać więcej informacji o zapytaniu, lub użyć wywoływania funkcji w przypadku czatu i metod asynchronicznych.

Dodatkowe przykłady kodu znajdziesz w przykładowym notatniku dotyczącym wywoływania funkcji w Gemini.

12. Gratulacje

Za pomocą wywoływania funkcji w Gemini udało Ci się utworzyć potok generatywnej AI, który korzysta z interfejsu Vertex AI Gemini API i Pythona. Użytkownicy mogą zadawać pytania o kursy wymiany walut, a system pobierze najnowsze dane z zewnętrznego interfejsu API i odpowie na pytanie.

W przypadku promptu od użytkownika funkcja wywoływania funkcji w Gemini wybiera odpowiednią funkcję, wyodrębnia z promptu parametry i zwraca obiekt danych strukturalnych, który umożliwia wywołanie zewnętrznego interfejsu API.

Funkcja wywoływania funkcji w Gemini została zaprojektowana tak, aby zapewnić Ci najlepsze z obu światów w zakresie deterministycznego wyodrębniania parametrów, pozostawiając podsumowywanie i tworzenie treści modelowi generatywnemu. Możesz wypróbować inne interfejsy API i prompty w swoim potoku oraz poznać inne funkcje dostępne w Gemini API w Vertex AI.

Interfejs API

Czyszczenie

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym Codelabs, wykonaj te czynności czyszczenia:

Więcej informacji

Aby dowiedzieć się więcej o konwersacyjnej i generatywnej AI, zapoznaj się z tymi przewodnikami i zasobami:

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.