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

1. Omówienie

Co to jest wywoływanie funkcji w Gemini?

Vertex AI Gemini API to rodzina modeli generatywnej AI opracowanych przez Google DeepMind, które zostały zaprojektowane z myślą o multimodalnych zastosowaniach. Wywoływanie funkcji to funkcja modeli Gemini, która ułatwia deweloperom uzyskiwanie danych wyjściowych uporządkowanych danych z modeli generatywnych.

Programiści mogą następnie używać tych danych wyjściowych do wywoływania innych interfejsów API i zwracania odpowiednich danych odpowiedzi do modelu. Inaczej mówiąc, wywoływanie funkcji pomaga połączyć modele generatywne z systemami zewnętrznymi, aby generowane treści zawierały 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 przekażesz deklaracje funkcji w zapytaniu do modelu generatywnego, model zwróci uporządkowany obiekt zawierający nazwy odpowiednich funkcji oraz ich argumenty na podstawie zapytania użytkownika. Pamiętaj, że w przypadku wywołania funkcji model jej nie wywołuje. Zamiast tego możesz użyć zwróconej funkcji i parametrów, aby wywołać ją w dowolnym języku, bibliotece lub platformie.

Interfejs API

Co utworzysz

W ramach tego ćwiczenia w Codelabs utworzysz potok generatywnej AI przy użyciu interfejsu Vertex AI Gemini API oraz Pythona. Korzystając z aplikacji, użytkownicy mogą zapytać o kursy wymiany, a system pobierze najnowsze dane z zewnętrznego interfejsu API i udzieli odpowiedzi.

Czego się nauczysz

  • Jak korzystać z modelu Gemini za pomocą biblioteki klienta w Pythonie
  • Jak zdefiniować deklarację funkcji i zarejestrować ją jako narzędzie
  • Jak wywołać Gemini i uzyskać odpowiedź na wywołanie funkcji
  • Jak zwrócić 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 w Pythonie.

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ć interfejs Vertex AI API w projekcie Google Cloud.

Instalowanie biblioteki klienta Pythona dla Vertex AI

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

  1. Otwórz terminal w środowisku programistycznym.
  2. Sprawdź, czy masz prawidłowe środowisko programistyczne Pythona, i w razie potrzeby skorzystaj z tych wskazówek.
  3. Uruchom to polecenie, aby zainstalować bibliotekę klienta Pythona dla Vertex AI:
    pip install --upgrade google-cloud-aiplatform
    
  4. Jeśli pracujesz w środowisku notatników, korzystanie z nowo zainstalowanych pakietów może wymagać ponownego uruchomienia środowiska wykonawczego lub jądra systemu.

Możesz teraz korzystać z interfejsu Vertex AI API.

3. Interpretacja problemu

Czy zdarzyło Ci się kiedyś wejść w interakcję z dużym modelem językowym lub generatywnym AI i pytać o informacje w czasie rzeczywistym lub w czasie rzeczywistym, aby otrzymać odpowiedź, która zawiera nieaktualne lub nieprecyzyjne informacje?

Spróbujmy teraz. Najpierw zaimportujemy odpowiednie pakiety Pythona i zainicjujemy model Gemini. Ten kod możesz uruchomić w środowisku programistycznym Pythona, takim jak Colab lub Colab Enterprise, i zainstalować najnowszą wersję pakietu SDK Vertex AI dla Pythona:

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

Zadajmy teraz pytanie dotyczące kursu 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ć interesujące go waluty, pobrać najnowszy kurs wymiany i samodzielnie dokonać konwersji.

W idealnej sytuacji potok modelu generatywnego może obsługiwać niektóre lub wszystkie te zadania za użytkownika. W następnej sekcji wypróbujesz typowe obejścia problemów z ustrukturyzowanymi odpowiedziami z modeli generatywnych, które pozwolą Ci wywoływać systemy zewnętrzne.

4. Typowe sposoby obejścia tego problemu

Podczas pracy z modelami generatywnymi w sytuacjach, gdy potrzebujesz aktualnych informacji lub danych z zewnętrznych źródeł, możesz wywołać zewnętrzny interfejs API, a następnie przesłać wyniki z powrotem do modelu generatywnego, który zostanie wykorzystany w swojej odpowiedzi.

Zanim wywołasz system zewnętrzny, musisz wybrać odpowiednią funkcję, wyodrębnić odpowiednie parametry od użytkownika i umieścić je w obiekcie uporządkowanych danych. Zwykle wymaga to kompleksowej inżynierii promptów, aby zmusić model generatywny do generowania prawidłowych uporządkowanych danych.

Wróćmy do pytania, które zadaliśmy w poprzedniej sekcji, i dodajmy kilka dodatkowych instrukcji dotyczących modelu. Spróbuj wysłać to żądanie do modelu Gemini:

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)

Wynikiem jest poniższa odpowiedź tekstowa, która nie jest prawidłowym plikiem JSON i utrudnia nam pracę:

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

W szczególności pierwszy i ostatni wiersz odpowiedzi tekstowej zawiera grawis, który oddziela 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 do prawidłowego formatu JSON i słownika, dodać do promptu więcej instrukcji, podać co najmniej 1 przykład żądanych danych wyjściowych, dostroić model lub ponownie wywołać model generatywny z prośbą o wyczyszczenie pliku JSON.

Ale jest bardziej deterministyczny sposób! Dowiedz się, jak używać wywołań funkcji w Gemini do wysyłania zapytań o informacje w usługach zewnętrznych i zwracania trafnych odpowiedzi użytkownikom.

5. Jak działa wywoływanie funkcji

Zanim zaczniemy wyodrębnianie parametrów i wywoływanie funkcji, omówimy kroki wywoływania funkcji i informacje o komponentach używanych w czasie działania.

Omówienie wywołań funkcji w Gemini

Dane wejściowe użytkownika w Gemini API

Prompt użytkownika jest wysyłany do interfejsu Gemini API. W tym wywołaniu interfejsu API do modelu Gemini deweloper zdefiniował co najmniej 1 deklarację funkcji w narzędziu, dzięki czemu model Gemini wie, które funkcje może wywoływać i jak je wywoływać.

Interfejs Gemini API zwraca wywołanie funkcji

Na podstawie danych wejściowych i promptów użytkownika Gemini zwróci odpowiedź wywołania funkcji z uporządkowanymi danymi zawierającymi nazwę funkcji do wywołania i odpowiadające jej parametry.

Tworzenie żądania do interfejsu API

Następnie użyj nazwy i parametrów funkcji do wysłania żądania do interfejsu API, które ma pobrać informacje z zewnętrznego systemu lub interfejsu API. To żądanie i odpowiedź do interfejsu API jest wdrażane przez dewelopera w kodzie aplikacji i odbywa się poza zakresem Gemini API i pakietu SDK. Możesz na przykład użyć biblioteki requests w Pythonie, aby wywołać interfejs API REST i otrzymać odpowiedź JSON. Możesz też wywołać tę funkcję, używając preferowanej metody i biblioteki klienta.

Zwracanie odpowiedzi interfejsu API do Gemini

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

6. Wybierz interfejs API

Znasz już cały proces i konkretne kroki wywoływania funkcji. Teraz utworzysz potok generatywnej AI, który będzie pobierać najnowsze kursy walut. Najpierw musimy wybrać interfejs API, którego chcemy użyć jako źródła informacji.

W naszej aplikacji do wymiany walut wykorzystamy interfejs API REST dostępny na stronie https://www.frankfurter.app/, aby pobrać najnowsze informacje o globalnych kursach wymiany.

Aby móc korzystać z tego interfejsu API typu REST, możemy wywołać w Pythonie funkcję requests za pomocą wywołania interfejsu API REST:

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

lub cURL, na przykład:

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

zwraca odpowiedź podobną do:

{
  "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
  }
}

Wywołanie funkcji w Gemini nie powoduje faktycznego wywołania zewnętrznego interfejsu API, więc nie ma żadnych ograniczeń dotyczących typu interfejsu API, którego używasz. Możesz użyć usługi w Cloud Run, funkcji w Cloud Functions, żądania do interfejsu API kierowanego do usługi Google Cloud lub dowolnego zewnętrznego interfejsu API typu REST.

7. Zdefiniuj funkcję i narzędzie

Po wybraniu interfejsu API typu 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")

Na podstawie informacji o interfejsie API typu 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 zostanie przeliczony

to

Ciąg znaków

Waluta, na którą zostanie przeliczona

date

Ciąg znaków

Data pobrania kursu wymiany dla

Przy użyciu 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

Zarejestrujmy teraz ten adres jako FunctionDeclaration przy użyciu 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 stosuj jak najwięcej szczegółów, ponieważ model generatywny użyje tych informacji do określenia, którą funkcję wybrać i jak wypełnić parametry w wywołaniu funkcji.

Na koniec określ pole Tool zawierające deklarację funkcji:

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

W tym przypadku używasz jednej deklaracji funkcji w narzędziu, ale pamiętaj, że możesz zarejestrować 1 lub więcej deklaracji funkcji w narzędziu, a model wybierze odpowiednią funkcję do użycia w czasie działania. Więcej informacji na temat FunctionDeclaration, Tool i powiązanych klas w pakiecie SDK Gemini dla Pythona znajdziesz w dokumentacji dotyczącej wywoływania funkcji w interfejsie Gemini API.

Zakończono konfigurowanie definicji funkcji i narzędzi. W następnej sekcji wywołamy model generatywny za pomocą tego narzędzia i otrzymasz wywołanie funkcji, za pomocą którego będziemy mogli wywołać interfejs API REST.

8. Wygeneruj wywołanie funkcji

Teraz możesz wyświetlić prompt dla modelu generatywnego i uwzględnić zdefiniowany przez siebie 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ł 1 dostępną funkcję i zwrócił wywołanie funkcji get_exchange_rate wraz z parametrami. Parametry mają właściwy format, na którym nam zależy. Świetnie, że otrzymujesz uporządkowane odpowiedzi z modeli generatywnych.

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

9. Tworzenie żądania do interfejsu API

Pamiętaj, że wywołanie funkcji w Gemini nie powoduje faktycznego wywołania interfejsu API za Ciebie. Zamiast tego, możesz użyć dowolnego języka, biblioteki lub platformy.

W tym przykładzie użyjesz biblioteki requests w Pythonie do wywołania interfejsu API REST kursu wymiany.

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 wywołać metodę requests lub dowolną inną:

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

Efektem jest odpowiedź podobna do:

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

W odpowiedzi otrzymaliśmy też interfejs API typu REST, uwzględniając najnowsze informacje o kursie wymiany z dzisiaj. W następnej sekcji przekażemy te informacje z powrotem do modelu, aby mógł wygenerować odpowiednią odpowiedź dla użytkownika.

10. Generowanie odpowiedzi

Wygenerujmy odpowiedź dla użytkownika, przekazując ją z powrotem modelowi w następnym turze wątku:

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, zareaguje on na prompt użytkownika wraz z odpowiednimi informacjami 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. Zobacz przykładowy pełny kod

W tym momencie możesz umieścić kod Pythona w interfejsie API backendu za pomocą usługi Cloud Run, funkcji w Cloud Functions lub innej usługi w chmurze i wdrożyć aplikację frontendową, która korzysta z tego interfejsu API backendu do wykonywania zapytań dotyczących modelu 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: jedno żądanie wygenerowania wywołania funkcji, a drugie żądanie zwrócenia odpowiedzi funkcji. Pamiętaj, że jest to tylko 1 metoda obsługi wywołań funkcji i odpowiedzi funkcji w Gemini. Możesz też wykonywać dodatkowe wywołania funkcji, aby uzyskać więcej informacji na temat zapytania, lub używać wywołań funkcji z użyciem czatu i metod asynchronicznych.

Więcej przykładów kodu znajdziesz w przykładowym notatniku dotyczącym wywoływania funkcji w Gemini.

12. Gratulacje

Dzięki wywołaniu funkcji w Gemini udało Ci się utworzyć potok generatywnej AI wykorzystujący interfejs Vertex AI Gemini API oraz Pythona. Użytkownicy mogą zapytać o kursy wymiany, a system pobierze najnowsze dane z zewnętrznego interfejsu API i udzieli odpowiedzi.

Na podstawie promptu użytkownika wywołanie funkcji w Gemini zajmuje się wybraniem odpowiedniej funkcji, wyodrębnieniem parametrów z promptu i zwróceniem obiektu uporządkowanych danych w celu wykonania zewnętrznego wywołania interfejsu API.

Konstrukcja wywołań funkcji w Gemini ma na celu zapewnienie Ci najlepszych z obu światów w zakresie deterministycznego wyodrębniania parametrów, a podsumowywanie i tworzenie treści pozostawiamy modelowi generatywnemu. Możesz wypróbować inne interfejsy API i prompty w swoim potoku oraz wypróbować inne funkcje związane z Vertex AI Gemini API.

Interfejs API

Czyszczenie

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte podczas tego ćwiczenia z programowania, możesz wykonać te czyszczenie:

Więcej informacji

Aby dowiedzieć się więcej o konwersacyjnej AI i generatywnej AI, skorzystaj z tych przewodników i materiałów:

Licencja

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