Interfejs Prompt API umożliwia deweloperom wykonywanie zadań związanych z przetwarzaniem języka naturalnego bezpośrednio w przeglądarce za pomocą Gemini Nano. To podejście oparte na wbudowanej AI zapewnia prywatność użytkowników, obniża koszty serwerów i umożliwia działanie w trybie offline.
1. Pierwsze kroki i wymagania sprzętowe
Interfejs Prompt API jest obecnie dostępny w Chrome od wersji 148 (na komputery) na systemy Windows, macOS, Linux i Chromebook Plus.
Wymagania sprzętowe
- Miejsce na dane: 22 GB wolnego miejsca (na początkowy profil i model).
- Pamięć/procesor: 16 GB pamięci RAM i co najmniej 4 rdzenie procesora.
- GPU: co najmniej 4 GB pamięci VRAM (wymagane w przypadku wejścia audio).
- Sieć: wymagana tylko do początkowego pobrania modelu.
Inicjowanie interfejsu API
Przed rozpoczęciem pobierania sprawdź dostępność modelu:
const availability = await LanguageModel.availability();
// Do not call create() when unavailable — the model cannot run on this device.
if (availability !== 'unavailable') {
const session = await LanguageModel.create({
monitor(m) {
// Inform the user while the model downloads so the UI doesn't appear frozen.
m.addEventListener('downloadprogress', (e) => {
console.log(`Downloaded ${e.loaded * 100}%`);
});
},
});
}
2. Podstawowe możliwości promptów
W przykładach sesji w tej sekcji pominięto session.destroy(), aby zachować zwięzłość. Zawsze wywołuj metodę session.destroy(), gdy sesja nie jest już potrzebna, aby zwolnić pamięć urządzenia (patrz sekcja 5).
Podstawowe i strumieniowe dane wyjściowe
W przypadku krótkich odpowiedzi użyj prompt(). W przypadku dłuższych treści użyj promptStreaming(), aby zapewnić bardziej elastyczny interfejs.
OBOWIĄZKOWO: nigdy nie przypisuj danych wyjściowych modelu do zmiennej innerHTML. Dane wyjściowe modelu są niezaufane i mogą zawierać wstrzyknięte znaczniki. Zawsze używaj textContent lub środka dezynfekującego.
const session = await LanguageModel.create();
// prompt() accumulates the full response before resolving — use for short, one-shot output.
const result = await session.prompt('Write a haiku about coding.');
// textContent, not innerHTML — model output is untrusted and must not be parsed as markup.
outputEl.textContent = result;
// promptStreaming() yields independent chunks that must be concatenated;
// use for longer content so each chunk can be rendered progressively.
const stream = session.promptStreaming('Write a long story about a robot.');
let completeResult = '';
for await (const chunk of stream) {
completeResult += chunk;
outputEl.append(chunk);
}
console.log('Full story:', completeResult);
Dane wejściowe w różnych formatach
Interfejs Prompt API obsługuje dane wejściowe w formie tekstu, dźwięku i obrazu (obrazy, canvas, klatki wideo).
const session = await LanguageModel.create({
// Declaring expected input types lets the browser optimize model loading.
expectedInputs: [{ type: 'text' }, { type: 'image' }],
expectedOutputs: [{ type: 'text' }],
});
const response = await session.prompt([
{
role: 'user',
content: [
{ type: 'text', value: 'What is in this image?' },
{ type: 'image', value: document.querySelector('canvas') },
],
},
]);
3. Zaawansowane zarządzanie sesjami
Sesje umożliwiają modelowi zachowanie kontekstu w ramach wielu interakcji.
Kontekst i limit
Każda sesja ma maksymalny limit tokenów. Wykorzystanie możesz monitorować za pomocą session.contextUsage i session.contextWindow. Jeśli okno się przepełni, najstarsze wiadomości (z wyjątkiem instrukcji systemowych) zostaną usunięte.
Sesje klonowania
Klonowanie jest skutecznym sposobem na rozpoczynanie równoległych rozmów, które mają ten sam początkowy kontekst (np. osobowość „systemu”), bez konieczności ponownej inicjalizacji.
const mainSession = await LanguageModel.create({
initialPrompts: [{ role: 'system', content: 'You speak like a pirate.' }],
});
const branchA = await mainSession.clone();
const branchB = await mainSession.clone();
// Destroy the base after cloning — the clones own their own context from here.
mainSession.destroy();
Przywracanie poprzednich sesji
Funkcja „przywracania” jest jeszcze w fazie rozwoju, ale możesz odtworzyć sesję, wprowadzając poprzednią historię w initialPrompts.
Uwaga: localStorage jest niezaszyfrowany i trwały. Przechowywana historia rozmów może zawierać informacje umożliwiające identyfikację użytkownika. Przed zapisaniem historii czatu należy rozważyć kwestie związane z prywatnością.
// || '[]' ensures JSON.parse never receives null when the key doesn't exist yet.
const history = JSON.parse(localStorage.getItem('chat_history') || '[]');
const session = await LanguageModel.create({
initialPrompts: history, // Array of {role, content} objects
});
4. Ustrukturyzowane dane wyjściowe ze schematem JSON
Aby zapobiec dodawaniu przez model „pogawędek” (np. „Jasne, oto Twój kod JSON:”), użyj schematu JSON w polu responseConstraint. Dzięki temu dane wyjściowe są prawidłowym kodem JSON, który można natychmiast przeanalizować.
Przykład: klasyfikacja nastrojów
// Pass the schema as a plain object — do not JSON.stringify() it first.
const schema = {
type: 'object',
properties: {
rating: { type: 'number', minimum: 1, maximum: 5 },
is_positive: { type: 'boolean' },
},
required: ['rating', 'is_positive'],
};
const result = await session.prompt(
"Rate the following feedback: 'The food was great!'",
{ responseConstraint: schema },
);
const data = JSON.parse(result);
console.log(data.rating); // 5
Ograniczenia i prefiksy
Możesz dodatkowo ukierunkować model, wstępnie wypełniając odpowiedź asystenta za pomocą prefix: true.
const character = await session.prompt([
{ role: 'user', content: 'Create a character sheet' },
{ role: 'assistant', content: '```json\n', prefix: true },
]);
5. Sprawdzone metody i bezpieczeństwo
- Czyszczenie zasobów: zawsze wywołuj funkcję
session.destroy()po zakończeniu rozmowy, aby zwolnić pamięć. - Bezpieczeństwo danych wyjściowych: dane wyjściowe modelu są niezaufane. Zawsze zapisuj wyniki w
textContent, a nie winnerHTML, aby zapobiec wstrzykiwaniu XSS ze szkodliwych danych wyjściowych modelu. - Jeśli chcesz zezwolić na ograniczony kod HTML, użyj narzędzia do czyszczenia kodu, takiego jak natywny interfejs Sanitizer API lub DOMPurify.
- Anulowanie zadań: użyj
AbortController, aby umożliwić użytkownikom zatrzymywanie długotrwałych procesów generowania. Przekażsignaldoprompt()lubpromptStreaming(), a nie doLanguageModel.create(). - Bezpieczeństwo: używaj zasad uprawnień do kontrolowania dostępu w elementach iframe:
<iframe src="..." allow="language-model"></iframe>. - Projektowanie: zapoznaj się z przewodnikiem Ludzie + AI, aby zapewnić odpowiedzialne wdrażanie AI.
Łącząc ustrukturyzowane dane wyjściowe z zaawansowanym zarządzaniem sesjami, deweloperzy mogą tworzyć złożone, stanowe aplikacje AI, które działają całkowicie na urządzeniu użytkownika.
Zalecenia i ograniczenia
Pełną listę wskazówek znajdziesz na stronie https://developer.chrome.com/docs/ai/built-in-ai-dos-donts.md.txt. Oto najważniejsze informacje:
Przygotuj model w odpowiednim czasie
Dotyczy: wszystkich interfejsów API, np. Summarizer, Translator i Writer.
Zalecane: zainicjuj sesję, gdy tylko wyraźnie ustalisz, że użytkownik chce skorzystać z funkcji AI, np. gdy przejdzie do odpowiedniego interfejsu narzędzi AI, najedzie kursorem na obszar roboczy AI lub wejdzie w interakcję z interfejsem otaczającym funkcję. Wstępne rozgrzanie sesji umożliwia załadowanie modelu do pamięci w tle, gdy użytkownik konfiguruje zadanie, co eliminuje możliwe do uniknięcia opóźnienia związane z uruchomieniem na zimno. Staraj się być o krok do przodu, rozpoczynając kolejne najbardziej prawdopodobne zadanie wykonywane z pomocą AI, gdy tylko zaczniesz renderować bieżący wynik, np. jeśli funkcja jest przeznaczona do wielokrotnego użycia.
Nie: jeśli nie jest to konieczne, nie czekaj, aż użytkownik kliknie „Wygeneruj”, aby zainicjować sesję. Powoduje to opóźnienie zimnego startu, ponieważ model musi najpierw zostać wczytany do pamięci i przygotować potok wykonywania.
Ustawianie początkowych promptów podczas tworzenia
Dotyczy: Prompt API.
Zalecane: podaj instrukcje systemowe podczas inicjowania sesji, aby przyspieszyć działanie pierwszego prompta.
Nie: rozpocznij od pustej sesji i wyślij instrukcje systemowe w ramach pierwszego wywołania prompt(). Zwiększa to czas oczekiwania, ponieważ zmusza model do przetworzenia tych instrukcji w ostatniej chwili.
Klonowanie sesji w przypadku powtarzających się zadań
Dotyczy: Prompt API.
W przypadku interfejsu Prompt API każda sesja śledzi kontekst rozmowy, biorąc pod uwagę wszystkie poprzednie interakcje. Klon dziedziczy wszystko z sesji nadrzędnej, w tym początkowe prompty i całą historię interakcji do momentu klonowania, dlatego skonfiguruj użycie tak, aby dziedziczyć tylko to, czego potrzebujesz.
Zalecane czynności:
- Utwórz sesję podstawową: aby skutecznie obsługiwać niepowiązane zadania, utwórz sesję podstawową, która zawiera tylko instrukcje systemowe i nie zawiera poprzedniego kontekstu rozmowy.
- Sklonuj punkt odniesienia: użyj
clone()w tej sesji podstawowej do nowych zadań, aby uniknąć ponownego analizowania instrukcji systemowych. Dzięki temu możesz tworzyć równoległe rozmowy lub resetować zadanie do stanu początkowego.
Niezalecane:
- Nie używaj tej samej sesji do niepowiązanych zadań i unikaj klonowania sesji, która zawiera już niepotrzebną historię interakcji. Oba wzorce mogą powodować, że niepowiązany poprzedni kontekst będzie zakłócać bieżące zadanie.
- Nie wywołuj wielokrotnie funkcji
create()z tymi samymi instrukcjami systemowymi. Aby zoptymalizować wydajność, użyj wzorca klonowania.
Zniszcz nieużywane sesje
Dotyczy: wszystkich interfejsów API.
Zalecane: jawnie wywołuj metodę destroy() w sesjach, których już nie potrzebujesz, aby zwolnić pamięć, gdy funkcja nie jest już używana. Jeśli używasz wzorca klonowania, zachowaj sesję podstawową i usuń klony, których już nie potrzebujesz.
Nie: nie utrzymuj wielu aktywnych dużych sesji. Każda sesja zużywa pamięć, co powoduje niepotrzebne wykorzystanie zasobów i może stać się problemem. Sesje zostaną automatycznie usunięte przez moduł czyszczący pamięć, ale wywołanie destroy() szybciej zwolni pamięć.
Bezpieczne i wydajne renderowanie odpowiedzi przesyłanych strumieniowo
Dotyczy: wszystkich interfejsów API z obsługą strumieniowania (Prompt, Summarizer, Writer, Rewriter i Translator).
Zalecenie: traktuj wszystkie dane wyjściowe LLM jako treści niezaufane. Oczyść dane wyjściowe w całości, a nie tylko fragmenty, ponieważ szkodliwy kod może być podzielony na aktualizacje. Przed renderowaniem użyj interfejsu Sanitizer API, jeśli jest obsługiwany. Aby uniknąć spadku wydajności, użyj parsera Markdown do strumieniowania, takiego jak streaming-markdown.
Nie: ustawiaj bezpośrednio innerHTML przy każdej aktualizacji fragmentu. Jest to powolne, zwłaszcza w przypadku złożonego formatowania, takiego jak wyróżnianie składni, i podatne na wstrzykiwanie.
Optymalizuj dane wejściowe pod kątem szybkości
Dotyczy: wszystkich interfejsów API.
Zalecane: przekazuj modelowi tylko te informacje, które są ściśle niezbędne. Usuń wszystko, co nie jest istotne dla danego zadania. W przypadku dużych zbiorów danych podaj krótkie podsumowanie i niewielki wybór odpowiednich elementów.
Nie: wysyłaj do interfejsów API nieprzetworzonego tekstu, niepotrzebnych metadanych, tagów HTML ani dużych, nieprzefiltrowanych list. Czas oczekiwania znacznie się wydłuża wraz z rozmiarem danych wejściowych, co może sprawić, że funkcja oparta na AI będzie wydawać się uszkodzona na wielu urządzeniach.
Używanie ustrukturyzowanych danych wyjściowych w celu uzyskania przewidywalnych wyników
Dotyczy: Prompt API.
Zalecenie: jeśli chcesz, aby model zwracał dane w określonym formacie, użyj ustrukturyzowanych danych wyjściowych, podając pole responseConstraint, aby dostarczyć schemat JSON. Dzięki temu dane wyjściowe są przewidywalne i nie wymagają skomplikowanego przetwarzania końcowego ani ręcznego analizowania.
Nie: polegaj wyłącznie na instrukcjach w języku naturalnym (np. „wygeneruj tylko JSON”). Modele mogą zawierać wypełniacze konwersacyjne, które zakłócają działanie parsera.
Oddzielenie generowania od ograniczeń długości
Dotyczy: Prompt API, ponieważ jest to jedyny interfejs API, który obsługuje schematy ustrukturyzowanych danych wyjściowych.
Zalecane: pozwól modelowi wygenerować odpowiedź w naturalny sposób, a następnie użyj logiki po stronie klienta, aby skrócić tekst i dopasować go do interfejsu.
Nie: nie wymuszaj rygorystycznych limitów znaków, takich jak maxLength: 125, za pomocą schematów ustrukturyzowanych danych wyjściowych. Gdy odpowiedź modelu jest dłuższa niż ustawiony limit, model może przełączyć się na tokeny o wysokiej gęstości, takie jak języki obce lub emotikony, aby skompresować znaczenie, co może skutkować bezsensownymi wynikami.
Informowanie użytkownika
Dotyczy: wszystkich interfejsów API.
Zalecane: w zależności od złożoności i oczekiwanego czasu trwania zadania używaj animacji, wskazówek wizualnych i wskaźników postępu, aby informować użytkownika o stanie procesu. Optymalne podejście zależy od przypadku użycia i oczekiwanej długości danych wyjściowych interfejsu API. Oto kilka propozycji:
- Strumieniowanie długich treści: w przypadku podsumowań lub czatu strumieniowanie domyślnie tworzy efekt maszyny do pisania dla każdego tokena. Może to być naturalne i zapewniać natychmiastowe informacje zwrotne.
- Brak strumieniowania w przypadku krótkich zadań (lub długich zadań asynchronicznych): w przypadku krótkich danych wyjściowych, np. tekstu alternatywnego, brak strumieniowania może zapewnić bardziej dopracowany interfejs. Zapewnia też czas na spekulatywne przygotowanie kolejnego zadania wykonywanego z pomocą AI, podczas gdy bieżące jest renderowane. To podejście sprawdza się też w przypadku dłuższych zadań asynchronicznych lub zadań w tle. Jeśli użytkownik nie jest zablokowany na etapie generowania danych wyjściowych, nie ma pilnej potrzeby generowania ich w czasie rzeczywistym. Zasygnalizuj w interfejsie, że proces jest w toku.
- Wizualne przejścia podczas aktualizacji: podczas tłumaczenia lub przepisywania tekstu używaj animacji, np. przekształcania słów.
Nie: aktualizuj interfejsu bez wskazówek wizualnych.
Dostosowanie do modelu mentalnego użytkownika dotyczącego czasu i pracy
Dotyczy: wszystkich interfejsów API.
Zalecenie: jeśli odpowiedź jest niemal natychmiastowa, rozważ wprowadzenie sztucznego opóźnienia o sekundę lub dwie. Paradoksalnie użytkownicy mogą uznać wyniki za bardziej wiarygodne, gdy proces generowania będzie odpowiadał postrzeganej przez nich trudności zadania. Używaj animacji, aby zasygnalizować, że proces AI został zakończony.
Nie: zaskakuj użytkowników natychmiastowymi zmianami interfejsu.
Zezwalaj użytkownikom na szybkie poruszanie się i cofanie zmian wprowadzonych przez AI
Dotyczy: wszystkich interfejsów API.
Zalecane: wyposaż interfejs w kroki lub historię nawigacji, które pozwolą użytkownikom bez obaw przeglądać różne wyniki, i umożliwiaj im szybkie cofanie zmian wprowadzonych przez AI. Dzięki temu różne wersje są nadal łatwo dostępne.
Nie: nie zastępuj poprzedniej wersji roboczej użytkownika ani wyniku AI, który mógł mu się spodobać, bez możliwości cofnięcia, przywrócenia lub porównania wersji.
Zapewnianie użytkownikom kontroli i możliwości zastępowania ustawień
Dotyczy: wszystkich interfejsów API.
Zalecane: użytkownik powinien być ostatecznym edytującym wszystkich wygenerowanych treści. Zapewnij intuicyjne opcje zastępowania, aby użytkownik zachował pełną kontrolę nad ostatecznym wynikiem. Interfejsy API mogą generować nieprawidłowe wyniki.
Nie: nie wymuszaj wyniku wygenerowanego przez AI jako jedynej opcji.
buforowanie wyników zadań cyklicznych
Dotyczy: wszystkich interfejsów API.
Zalecane: wdróż lokalną pamięć podręczną wyników (np. za pomocą sessionStorage lub IndexedDB) na potrzeby powtarzających się danych wejściowych lub zapytań. Znormalizuj dane wejściowe, usuwając odstępy i zamieniając wielkie litery na małe, aby zwiększyć liczbę trafień w pamięci podręcznej. W przypadku dużych danych wejściowych, np. obrazów, wygeneruj hasz, który będzie używany jako klucz pamięci podręcznej. Ustaw konserwatywny czas życia danych (TTL) dla pamięci podręcznej (lub wyświetlaj wyniki z pamięci podręcznej, aktualizując je w tle). Pozwól użytkownikowi wywołać nowe wnioskowanie, jeśli wynik jest niezadowalający.
Nie: nie uruchamiaj ponownie tego samego wnioskowania w przypadku powtarzającego się zapytania lub identycznych danych wejściowych, gdy zmienność nie jest pożądana, np. gdy użytkownik przechodzi tam i z powrotem między wynikami wyszukiwania. Optymalizuje to czas reakcji i efektywne wykorzystanie lokalnych zasobów obliczeniowych.
6. Strategie zastępcze
Przed użyciem sprawdź, czy obiekt LanguageModel jest dostępny w zakresie globalnym:
if ('LanguageModel' in self) {
// The Prompt API is supported.
} else {
// Execute fallback strategy
}
Jeśli interfejs Prompt API nie jest obsługiwany lub sprawdzanie dostępności zwraca wartość „niedostępny”, musisz zastosować odpowiednie rozwiązanie zastępcze:
- Zdalny interfejs API jako rozwiązanie zastępcze: przekieruj żądanie wykrywania do punktu końcowego serwera lub interfejsu API w chmurze (takiego jak Vertex AI Gemini API).
- Lokalny interfejs API jako rozwiązanie zastępcze: przekieruj żądanie wykrywania do lokalnego punktu końcowego, na przykład za pomocą Transformers.js.