Generowanie treści za pomocą modeli AI

Sercem generatywnej AI są modele AI. Obecnie 2 najbardziej znane przykłady modeli generatywnych to duże modele językowe (LLM) i modele generowania obrazów. Modele te przyjmują dane wejściowe, tzw. prompt (najczęściej tekst, obraz lub ich kombinację), a na ich podstawie generują tekst, obraz, a nawet dźwięk lub film.

Wyniki działania tych modeli mogą być zaskakująco przekonujące: duże modele językowe generują tekst, który wygląda tak, jakby został napisany przez człowieka, a modele do generowania obrazów mogą tworzyć obrazy bardzo zbliżone do prawdziwych zdjęć lub dzieł sztuki stworzonych przez ludzi.

Modele LLM sprawdzają się też w innych zadaniach niż proste generowanie tekstu:

  • pisanie programów komputerowych;
  • planowanie podzadań, które są wymagane do wykonania większego zadania;
  • porządkowanie nieuporządkowanych danych;
  • Analizowanie i wyodrębnianie danych z korpusu tekstowego
  • wykonywanie automatycznych czynności na podstawie tekstu opisującego te czynności;

Dostępnych jest wiele modeli od różnych dostawców. Każdy model ma swoje mocne i słabe strony. Jeden model może się świetnie sprawdzać w jednym zadaniu, ale gorzej w innym. Aplikacje korzystające z generatywnej AI często mogą korzystać z różnych modeli w zależności od danego zadania.

Jako deweloper aplikacji zwykle nie wchodzisz w bezpośrednią interakcję z modelami AI generatywnej, ale korzystasz z usług dostępnych jako interfejsy API internetowe. Chociaż te usługi często mają podobne funkcje, wszystkie udostępniają je za pomocą różnych i niezgodnych interfejsów API. Jeśli chcesz korzystać z wielu usług modelowania, musisz używać ich zastrzeżonych pakietów SDK, które mogą być ze sobą niekompatybilne. Jeśli chcesz przejść z jednego modelu na najnowszy i najbardziej wydajny, być może trzeba będzie ponownie tworzyć integrację.

Genkit rozwiązuje to wyzwanie, udostępniając jeden interfejs, który abstrahuje szczegóły dostępu do potencjalnie dowolnej usługi modelu generatywnej AI, z kilkoma gotowymi implementacjami. Tworzenie aplikacji z wykorzystaniem AI na podstawie Genkit upraszcza proces tworzenia pierwszego wywołania generatywnej AI i ułatwia łączenie wielu modeli lub zastępowanie jednego modelu innym w miarę pojawiania się nowych modeli.

Zanim zaczniesz

Jeśli chcesz uruchomić przykłady kodu na tej stronie, najpierw wykonaj czynności opisane w przewodniku Początkujący. We wszystkich przykładach zakładamy, że masz już zainstalowaną bibliotekę Genkit jako zależność w projekcie.

Modele obsługiwane przez Genkit

Genkit został zaprojektowany tak, aby był na tyle elastyczny, aby można było używać go z dowolną usługą generatywnej AI. Jej podstawowe biblioteki definiują wspólny interfejs do pracy z modelami, a wtyczki modela definiują szczegóły implementacji do pracy z konkretnym modelem i jego interfejsem API.

Zespół Genkit obsługuje wtyczki do pracy z modelami udostępnianymi przez Vertex AI, Google Generative AI i Ollama:

  • rodzinę dużych modeli językowych Gemini za pomocą wtyczki Google Cloud Vertex AI.
  • rodziny dużych modeli językowych Gemini za pomocą wtyczki Google AI.
  • modele generowania obrazów Imagen2 i Imagen3 za pomocą Vertex AI w Google Cloud;
  • rodzina modeli LLM Claude 3 firmy Anthropic, dostępna w ramach ogrodu modeli Vertex AI od Google Cloud;
  • Gemma 2, Llama 3 i wiele innych otwartych modeli za pomocą wtyczki Ollama (musisz samodzielnie hostować serwer Ollama).

Oprócz tego istnieje kilka wtyczek obsługiwanych przez społeczność, które zapewniają interfejsy do tych modeli:

Więcej informacji znajdziesz na stronie npmjs.org, wyszukując pakiety oznaczone tagiem genkit-model.

Wczytywanie i konfigurowanie wtyczek modeli

Zanim zaczniesz generować treści za pomocą Genkit, musisz załadować i skonfigurować wtyczkę modelu. Jeśli korzystasz z tego przewodnika po zapoznaniu się z poprzednim, masz już to za sobą. W przeciwnym razie zapoznaj się z poradnikiem Pierwsze kroki lub dokumentacją konkretnego wtyczki i wykonaj podane w niej instrukcje.

Metoda generate()

W Genkit głównym interfejsem, za pomocą którego możesz wchodzić w interakcje z modelami generatywnej AI, jest metoda generate().

Najprostsze wywołanie generate() określa model, którego chcesz użyć, oraz prompt tekstowy:

import { gemini15Flash, googleAI } from '@genkit-ai/googleai';
import { genkit } from 'genkit';

const ai = genkit({
  plugins: [googleAI()],
  model: gemini15Flash,
});

(async () => {
  const { text } = await ai.generate(
    'Invent a menu item for a pirate themed restaurant.'
  );
  console.log(text);
})();

Po wykonaniu tego krótkiego przykładu zostanie wydrukowana pewna ilość informacji debugujących, a następnie dane wyjściowe wywołania funkcji generate(), które zwykle będą zawierać tekst w formacie Markdown, jak w tym przykładzie:

## The Blackheart's Bounty

**A hearty stew of slow-cooked beef, spiced with rum and molasses, served in a
hollowed-out cannonball with a side of crusty bread and a dollop of tangy
pineapple salsa.**

**Description:** This dish is a tribute to the hearty meals enjoyed by pirates
on the high seas. The beef is tender and flavorful, infused with the warm spices
of rum and molasses. The pineapple salsa adds a touch of sweetness and acidity,
balancing the richness of the stew. The cannonball serving vessel adds a fun and
thematic touch, making this dish a perfect choice for any pirate-themed
adventure.

Uruchom ponownie skrypt, aby uzyskać inny wynik.

Poprzedni przykładowy kod wysłał żądanie generowania do domyślnego modelu, który został określony podczas konfigurowania instancji Genkit.

Możesz też określić model dla pojedynczego wywołania funkcji generate():

const { text } = await ai.generate({
  model: gemini15Pro,
  prompt: 'Invent a menu item for a pirate themed restaurant.',
});

W tym przykładzie używamy odwołania do modelu wyeksportowanego przez wtyczkę modelu. Inną opcją jest określenie modelu za pomocą identyfikatora ciągu znaków:

const { text } = await ai.generate({
  model: 'googleai/gemini-1.5-pro-latest',
  prompt: 'Invent a menu item for a pirate themed restaurant.',
});

Identyfikator modelu w postaci ciągu znaków ma postać providerid/modelid, gdzie identyfikator dostawcy (w tym przypadku googleai) identyfikuje wtyczkę, a identyfikator modelu to identyfikator w postaci ciągu znaków specyficzny dla danej wersji wtyczki.

Niektóre wtyczki modeli, np. wtyczka Ollama, zapewniają dostęp do potencjalnie kilkudziesięciu różnych modeli, dlatego nie eksportują poszczególnych odwołań do modeli. W takich przypadkach możesz określić model tylko za pomocą atrybutu generate(), podając jego identyfikator ciągu znaków.

Te przykłady ilustrują też ważną kwestię: gdy używasz funkcji generate() do wywoływania modeli generatywnej AI, zmiana modelu, którego chcesz użyć, polega po prostu na przekazaniu innej wartości parametrowi model. Korzystając z pakietu generate() zamiast pakietu SDK natywnego modelu, zyskujesz elastyczność, która ułatwi Ci używanie w aplikacji kilku różnych modeli i zmianę modeli w przyszłości.

Do tej pory pokazaliśmy Ci tylko przykłady najprostszych wywołań generate(). generate() udostępnia też interfejs do bardziej zaawansowanych interakcji z modelami generacyjnymi, co opiszemy w następnych sekcjach.

Prompty systemowe

Niektóre modele obsługują prompt systemowy, który zawiera instrukcje dotyczące tego, jak model ma reagować na wiadomości od użytkownika. Za pomocą promptu systemowego możesz określić personę, którą model ma przyjąć, ton jego odpowiedzi, format jego odpowiedzi itp.

Jeśli model, którego używasz, obsługuje prompty systemowe, możesz podać taki prompt za pomocą parametru system:

const { text } = await ai.generate({
  system: 'You are a food industry marketing consultant.',
  prompt: 'Invent a menu item for a pirate themed restaurant.',
});

Parametry modelu

Funkcja generate() przyjmuje parametr config, za pomocą którego możesz określić opcjonalne ustawienia, które kontrolują sposób generowania treści przez model:

const { text } = await ai.generate({
  prompt: 'Invent a menu item for a pirate themed restaurant.',
  config: {
    maxOutputTokens: 400,
    stopSequences: ['<end>', '<fin>'],
    temperature: 1.2,
    topP: 0.4,
    topK: 50,
  },
});

Dokładne parametry, które są obsługiwane, zależą od modelu i od API. Parametry w poprzednim przykładzie są jednak wspólne dla niemal każdego modelu. Oto wyjaśnienie tych parametrów:

Parametry kontrolujące długość danych wyjściowych

maxOutputTokens

Duże modele językowe działają na jednostkach zwanych tokenami. Token zwykle, ale niekoniecznie, jest mapowany na określoną sekwencję znaków. Gdy przekazujesz prompt do modelu, jednym z pierwszych kroków jest znakowanie promptu na ciąg znaków. Następnie LLM generuje sekwencję tokenów na podstawie pofragmentowanego wejścia. Na koniec sekwencja tokenów jest ponownie konwertowana na tekst, który jest wyjściem.

Parametr maksymalna liczba tokenów wyjściowych określa po prostu, ile tokenów ma wygenerować model LLM. Każdy model może używać innego tokenizera, ale dobrą regułą jest uznawanie, że jedno słowo w języku angielskim składa się z 2–4 tokenów.

Jak już wspomnieliśmy, niektóre tokeny mogą nie być mapowane na sekwencje znaków. Przykładem może być token wskazujący koniec sekwencji: gdy LLM wygeneruje ten token, przestaje generować kolejne. Dlatego może się zdarzyć, że LLM wygeneruje mniej tokenów niż maksymalną liczbę, ponieważ wygenerował token „stop”.

stopSequences

Ten parametr umożliwia ustawienie tokenów lub sekwencji tokenów, które po wygenerowaniu wskazują koniec danych wyjściowych LLM. Prawidłowe wartości, których należy tu używać, zależą od sposobu trenowania modelu i zwykle są ustawiane przez wtyczkę modelu. Jeśli jednak model wygenerował inną sekwencję stop, możesz ją tutaj podać.

Pamiętaj, że określasz ciągi znaków, a nie tokeny. W większości przypadków podajesz sekwencję znaków, którą model tokenizera mapuje na pojedynczy token.

Parametry, które kontrolują „kreatywność”

Parametry temperatura, górne pgórne k określają razem, na ile „kreatywny” ma być model. Poniżej znajdziesz krótkie wyjaśnienia znaczenia tych parametrów, ale ważniejsze jest to, że służą one do dostosowywania charakteru danych wyjściowych LLM. Ich optymalne wartości zależą od Twoich celów i preferencji i najprawdopodobniej można je znaleźć tylko przez eksperymentowanie.

temperature

Duże modele językowe to maszyny do przewidywania tokenów. W przypadku danej sekwencji tokenów (np. prompta) LLM przewiduje dla każdego tokena w swoim słowniku prawdopodobieństwo, że token będzie następny w sekwencji. Temperatura to współczynnik skalowania, przez który dzieli się te prognozy przed ich znormalizowaniem do prawdopodobieństwa w zakresie od 0 do 1.

Niska wartość temperatury (w zakresie od 0,0 do 1,0) zwiększa różnicę w prawdopodobieństwo między tokenami, przez co model będzie jeszcze mniej skłonny do wygenerowania tokenu, który został już oceniony jako mało prawdopodobny. Jest on często postrzegany jako mniej kreatywny. Chociaż 0,0 nie jest technicznie prawidłową wartością, wiele modeli interpretuje ją jako sygnał, że model powinien działać deterministycznie i uwzględniać tylko jeden najbardziej prawdopodobny token.

Wysokie wartości temperatury (czyli większe niż 1,0) powodują kompresję różnic w prawdopodobieństwie między tokenami, przez co model częściej generuje tokeny, które wcześniej zostały ocenione jako mało prawdopodobne. Jest ono często postrzegane jako bardziej kreatywne. Niektóre interfejsy API modeli narzucają maksymalną temperaturę, często 2,0.

topP

Top-p to wartość z zakresu od 0,0 do 1,0, która określa liczbę możliwych tokenów, które model ma wziąć pod uwagę, przez określenie skumulowanego prawdopodobieństwa tokenów. Na przykład wartość 1,0 oznacza, że należy wziąć pod uwagę wszystkie możliwe tokeny (ale nadal uwzględniać prawdopodobieństwo każdego z nich). Wartość 0,4 oznacza uwzględnianie tylko najbardziej prawdopodobnych tokenów, których prawdopodobieństwa dają w sumie 0,4, oraz wykluczanie pozostałych tokenów.

topK

Top-K to wartość całkowita, która również kontroluje liczbę możliwych tokenów, które model ma wziąć pod uwagę, ale tym razem poprzez jawne określenie maksymalnej liczby tokenów. Podanie wartości 1 oznacza, że model powinien zachowywać się deterministycznie.

Eksperymentowanie z parametrami modelu

Korzystając z interfejsu dla programistów, możesz eksperymentować z wpływem tych parametrów na dane wyjściowe generowane przez różne kombinacje modeli i promptów. Uruchom interfejs programisty za pomocą polecenia genkit start. Automatycznie wczyta on wszystkie modele zdefiniowane przez wtyczki skonfigurowane w projekcie. Możesz szybko wypróbować różne prompty i wartości konfiguracji bez konieczności wielokrotnego wprowadzania tych zmian w kodzie.

Dane wyjściowe uporządkowane

Gdy używasz generatywnej AI jako komponentu w aplikacji, często chcesz uzyskać dane w innym formacie niż zwykły tekst. Nawet jeśli generujesz tylko treści do wyświetlenia użytkownikowi, możesz skorzystać z wyjścia ustrukturyzowanego, aby prezentować je w bardziej atrakcyjny sposób. W przypadku bardziej zaawansowanych zastosowań generatywnej AI, takich jak programowe wykorzystanie danych wyjściowych modelu lub podawanie danych wyjściowych jednego modelu innemu, konieczne jest uporządkowanie danych wyjściowych.

W Genkit możesz poprosić o uporządkowane dane wyjściowe z modelu, podając schemat podczas wywołania funkcji generate():

import { z } from 'genkit'; // Import Zod, which is re-exported by Genkit.
const MenuItemSchema = z.object({
  name: z.string(),
  description: z.string(),
  calories: z.number(),
  allergens: z.array(z.string()),
});

const { output } = await ai.generate({
  prompt: 'Invent a menu item for a pirate themed restaurant.',
  output: { schema: MenuItemSchema },
});

Schematy danych wyjściowych modelu są określane za pomocą biblioteki Zod. Oprócz języka definiowania schematów Zod zapewnia też sprawdzanie typu w czasie wykonywania, które łączy statyczne typy TypeScript z nieprzewidywalnymi wynikami modeli generatywnej AI. Zod umożliwia pisanie kodu, który może polegać na tym, że wywołanie generate zawsze zwróci dane wyjściowe zgodne z typami TypeScript.

Gdy określisz schemat w pliku generate(), Genkit wykona kilka czynności w tle:

  • Dodaje do promptu dodatkowe wskazówki dotyczące pożądanego formatu danych wyjściowych. Ma to też efekt uboczny w postaci określenia dla modelu, jakie dokładnie treści chcesz generować (np. nie tylko sugerować pozycję menu, ale też generować jej opis, listę alergenów itp.).
  • Parsuje dane wyjściowe modelu na obiekt JavaScript.
  • Sprawdza, czy dane wyjściowe są zgodne ze schematem.

Aby uzyskać ustrukturyzowany wynik po pomyślnym wywołaniu metody generate, użyj właściwości output obiektu odpowiedzi:

if (output) {
  const { name, description, calories, allergens } = output;
}

Obsługa błędów

W poprzednim przykładzie właściwość output może mieć wartość null. Może się to zdarzyć, gdy model nie wygeneruje danych wyjściowych zgodnych ze schematem. Najlepsza strategia postępowania w przypadku takich błędów zależy od konkretnego przypadku, ale oto kilka ogólnych wskazówek:

  • Wypróbuj inny model. Aby dane uporządkowane były generowane prawidłowo, model musi być w stanie generować dane w formacie JSON. Najpotężniejsze modele LLM, takie jak Gemini i Claude, są wystarczająco wszechstronne, aby to zrobić. Mniejsze modele, takie jak niektóre modele lokalne, których używasz z Ollama, mogą natomiast nie być w stanie niezawodnie generować danych wyjściowych w formie uporządkowanej, chyba że zostały specjalnie wytrenowane do tego celu.

  • Korzystanie z możliwości wymuszania w Zod: w schematach możesz określić, że Zod powinien próbować wymuszać niespełniające wymagań typy na typ określony w schemacie. Jeśli Twój schemat zawiera typy proste inne niż ciągi tekstowe, użycie narzucenia typu może zmniejszyć liczbę niepowodzeń generate(). W tej wersji funkcji MenuItemSchema do automatycznego korygowania sytuacji, w których model generuje informacje o kalorii jako ciąg znaków zamiast liczby, używane jest przymusowe konwertowanie typu:

    const MenuItemSchema = z.object({
      name: z.string(),
      description: z.string(),
      calories: z.coerce.number(),
      allergens: z.array(z.string()),
    });
    
  • Ponownie wywołaj generate(). Jeśli wybrany model tylko sporadycznie nie generuje zgodnego z standardami wyjścia, możesz traktować ten błąd jak błąd sieci i po prostu ponownie wysłać żądanie, stosując pewną strategię stopniowego wycofywania.

Streaming

Podczas generowania dużych ilości tekstu możesz ułatwić użytkownikom korzystanie z usługi, prezentując wyniki w miarę ich generowania (przesyłając je strumieniowo). Znajomy przykład strumieniowego przesyłania danych można zobaczyć w większości aplikacji do czatu z wykorzystaniem LLM: użytkownicy mogą czytać odpowiedzi modelu na ich wiadomości w miarę ich generowania, co zwiększa postrzeganą szybkość reakcji aplikacji i wzmacnia iluzję czatu z inteligentnym rozmówcą.

W Genkit możesz przesyłać dane wyjściowe strumieniowo za pomocą metody generateStream(). Jej składnia jest podobna do metody generate():

const { response, stream } = await ai.generateStream(
  'Suggest a complete menu for a pirate themed restaurant.'
);

Obiekt odpowiedzi ma właściwość stream, której możesz użyć do iteracji nad wyjściem strumieniowym żądania w miarę jego generowania:

for await (const chunk of stream) {
  console.log(chunk.text);
}

Podobnie jak w przypadku żądania niestrumieniowego, możesz też uzyskać pełny wynik:

const completeText = (await response).text;

Transmisja strumieniowa działa też z uporządkowanymi danymi wyjściowymi:

const MenuSchema = z.object({
  starters: z.array(MenuItemSchema),
  mains: z.array(MenuItemSchema),
  desserts: z.array(MenuItemSchema),
});

const { response, stream } = await ai.generateStream({
  prompt: 'Suggest a complete menu for a pirate themed restaurant.',
  output: { schema: MenuSchema },
});

for await (const chunk of stream) {
  // `output` is an object representing the entire output so far.
  console.log(chunk.output);
}

// Get the completed output.
const { output } = await response;

Strumieniowe generowanie danych ustrukturyzowanych działa nieco inaczej niż strumieniowe generowanie tekstu: właściwość output elementu odpowiedzi to obiekt utworzony z dotychczas wygenerowanych elementów, a nie obiekt reprezentujący pojedynczy element (który może być nieprawidłowy sam w sobie). Każdy fragment danych uporządkowanych w jakimś sensie zastępuje poprzedni fragment.

Na przykład pierwsze 5 wyjść z poprzedniego przykładu może wyglądać tak:

null

{ starters: [ {} ] }

{
  starters: [ { name: "Captain's Treasure Chest", description: 'A' } ]
}

{
  starters: [
    {
      name: "Captain's Treasure Chest",
      description: 'A mix of spiced nuts, olives, and marinated cheese served in a treasure chest.',
      calories: 350
    }
  ]
}

{
  starters: [
    {
      name: "Captain's Treasure Chest",
      description: 'A mix of spiced nuts, olives, and marinated cheese served in a treasure chest.',
      calories: 350,
      allergens: [Array]
    },
    { name: 'Shipwreck Salad', description: 'Fresh' }
  ]
}

Dane multimodalne

W przykładach, które do tej pory widzisz, jako prompty modelu użyto ciągów tekstowych. Chociaż jest to najczęstszy sposób inicjowania modeli generatywnej AI, wiele modeli może też akceptować inne media jako prompty. Prompty multimedialne są najczęściej używane w połączeniu z promptami tekstowymi, które instruują model, aby wykonał jakąś operację na mediach, np. dodał podpis do obrazu lub przepisał nagranie audio.

Możliwość akceptowania danych wejściowych w postaci multimediów oraz typy multimediów, których możesz używać, zależą całkowicie od modelu i jego interfejsu API. Na przykład modele z serii Gemini 1.5 mogą akceptować obrazy, filmy i dźwięk jako prompty.

Aby przekazać prompt multimedialny do modelu, który go obsługuje, zamiast przekazywać do generate prosty tekstowy prompt, prześlij tablicę zawierającą część multimedialną i tekstową:

const { text } = await ai.generate([
  { media: { url: 'https://example.com/photo.jpg' } },
  { text: 'Compose a poem about this image.' },
]);

W przykładzie powyżej obraz został wskazany za pomocą publicznie dostępnego adresu URL HTTPS. Możesz też przesłać dane multimedialne bezpośrednio, kodując je jako adres URL danych. Przykład:

import { readFile } from 'node:fs/promises';
const b64Data = await readFile('photo.jpg', { encoding: 'base64url' });
const dataUrl = `data:image/jpeg;base64,${b64Data}`;

const { text } = await ai.generate([
  { media: { url: dataUrl } },
  { text: 'Compose a poem about this image.' },
]);

Wszystkie modele, które obsługują dane wejściowe, obsługują zarówno adresy URL danych, jak i adresy URL HTTPS. Niektóre wtyczki do modeli umożliwiają obsługę innych źródeł multimediów. Na przykład wtyczka Vertex AI umożliwia też używanie adresów URL Cloud Storage (gs://).

Generowanie multimediów

Do tej pory większość przykładów na tej stronie dotyczyła generowania tekstu za pomocą modeli LLM. Genkit można jednak używać również z modelami generowania obrazów. Korzystanie z modelu generowania obrazów za pomocą funkcji generate() jest podobne do korzystania z modelu LLM. Aby na przykład wygenerować obraz za pomocą modelu Imagen2 w Vertex AI:

  1. Genkit używa adresów URL data: jako standardowego formatu wyjściowego wygenerowanych multimediów. Jest to standardowy format, który obsługuje wiele bibliotek. W tym przykładzie użyto pakietu data-urls z poziomu jsdom:

    npm i --save data-urls
    npm i --save-dev @types/data-urls
  2. Aby wygenerować obraz i zapisać go w pliku, wywołaj funkcję generate(), podając model generowania obrazów i typ multimediów w formacie wyjściowym:

    import { imagen3Fast, vertexAI } from '@genkit-ai/vertexai';
    import parseDataURL from 'data-urls';
    import { genkit } from 'genkit';
    
    import { writeFile } from 'node:fs/promises';
    
    const ai = genkit({
      plugins: [vertexAI({ location: 'us-central1' })],
    });
    
    (async () => {
      const { media } = await ai.generate({
        model: imagen3Fast,
        prompt: 'photo of a meal fit for a pirate',
        output: { format: 'media' },
      });
    
      if (media === null) throw new Error('No media generated.');
    
      const data = parseDataURL(media.url);
      if (data === null) throw new Error('Invalid "data:" URL.');
    
      await writeFile(`output.${data.mimeType.subtype}`, data.body);
    })();
    

Dalsze kroki

Więcej informacji o Genkit

  • Jako deweloper aplikacji możesz wpływać na wyniki generatywnych modeli AI głównie za pomocą promptów. Aby dowiedzieć się, jak Genkit pomaga tworzyć skuteczne prompty i nimi zarządzać w kodzie źródłowym, przeczytaj artykuł Zarządzanie promptami.
  • Chociaż generate() jest jądrem każdej aplikacji korzystającej z generatywnej AI, aplikacje używane w praktyce zwykle wymagają dodatkowej pracy przed wywołaniem modelu generatywnej AI i po jego wywołaniu. W związku z tym Genkit wprowadza pojęcie przepływów, które są definiowane jak funkcje, ale zawierają dodatkowe funkcje, takie jak możliwość obserwacji i uproszczone wdrażanie. Więcej informacji znajdziesz w artykule Definiowanie przepływów pracy.

Zaawansowane korzystanie z modeli LLM

  • Jedną z możliwości rozszerzenia możliwości LLM jest wyświetlenie użytkownikowi listy sposobów, w jaki LLM może poprosić o dodatkowe informacje, lub prośba o wykonanie jakiegoś działania. Nazywamy to wywoływaniem narzędzia lub wywoływaniem funkcji. Modele, które zostały wytrenowane pod kątem obsługi tej funkcji, mogą odpowiadać na prompty specjalnymi odpowiedziami, które wskazują aplikacji wywołującej, że powinna wykonać określone działanie i przesłać wynik z powrotem do LLM wraz z pierwotnym promptem. Genkit zawiera funkcje biblioteki, które automatyzują generowanie promptów i elementy pętli wywołania–odpowiedzi w ramach implementacji wywołania narzędzia. Więcej informacji znajdziesz w artykule Wywoływanie narzędzi.
  • Generowanie rozszerzone przez wyszukiwanie w zapisanych informacjach (RAG) to technika służąca do wprowadzania informacji dotyczących danej domeny do danych wyjściowych modelu. Polega to na wstawianiu odpowiednich informacji do promptu przed przekazaniem go do modelu językowego. Pełne wdrożenie RAG wymaga połączenia kilku technologii: modeli generowania wektorów dystrybucyjnych, baz danych wektorów i dużych modeli językowych. Zapoznaj się z artykułem Generowanie rozszerzone przez wyszukiwanie w zapisanych informacjach (RAG), aby dowiedzieć się, jak Genkit upraszcza proces koordynowania tych różnych elementów.

Testowanie danych wyjściowych modelu

Jako inżynier oprogramowania jesteś przyzwyczajony do systemów deterministycznych, w których ten sam rodzaj danych wejściowych zawsze daje ten sam wynik. Jednak modele AI są probabilistyczne, więc wyniki mogą się różnić w zależności od subtelnych niuansów danych wejściowych, danych treningowych modelu, a nawet losowości celowo wprowadzanej przez parametry takie jak temperatura.

Oceniacze Genkit mają strukturyzowane sposoby oceny jakości odpowiedzi LLM za pomocą różnych strategii. Więcej informacji znajdziesz na stronie Ocena.