Membuat sesi chat persisten

Banyak pengguna Anda akan berinteraksi dengan model bahasa besar untuk pertama kali melalui chatbot. Meskipun LLM mampu melakukan lebih dari sekadar menyimulasikan percakapan, model ini tetap merupakan gaya interaksi yang familier dan berguna. Meskipun pengguna Anda tidak akan berinteraksi langsung dengan model dengan cara ini, gaya perintah percakapan adalah cara yang efektif untuk memengaruhi output yang dihasilkan oleh model AI.

Untuk mendukung gaya interaksi ini, Genkit menyediakan serangkaian antarmuka dan abstraksi yang memudahkan Anda membuat aplikasi LLM berbasis chat.

Sebelum memulai

Sebelum membaca halaman ini, Anda harus sudah memahami konten yang dibahas di halaman Membuat konten dengan model AI.

Jika Anda ingin menjalankan contoh kode di halaman ini, selesaikan langkah-langkah dalam panduan Memulai terlebih dahulu. Semua contoh mengasumsikan bahwa Anda telah menginstal Genkit sebagai dependensi dalam project.

Dasar-dasar sesi chat

Berikut adalah aplikasi chatbot minimal berbasis konsol:

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

import { createInterface } from "node:readline/promises";

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

(async () => {
  const chat = ai.chat();
  console.log("You're chatting with Gemini. Ctrl-C to quit.\n");
  const readline = createInterface(process.stdin, process.stdout);
  while (true) {
    const userInput = await readline.question("> ");
    const { text } = await chat.send(userInput);
    console.log(text);
  }
})();

Sesi chat dengan program ini terlihat seperti contoh berikut:

You're chatting with Gemini. Ctrl-C to quit.

> hi
Hi there! How can I help you today? 

> my name is pavel
Nice to meet you, Pavel! What can I do for you today? 

> what's my name?
Your name is Pavel! I remembered it from our previous interaction. 

Is there anything else I can help you with?

Seperti yang dapat Anda lihat dari interaksi singkat ini, saat Anda mengirim pesan ke sesi chat, model dapat memanfaatkan sesi sejauh ini dalam responsnya. Hal ini mungkin karena Genkit melakukan beberapa hal di balik layar:

  • Mengambil histori chat, jika ada, dari penyimpanan (selengkapnya tentang persistensi dan penyimpanan nanti)
  • Mengirim permintaan ke model, seperti halnya generate(), tetapi secara otomatis menyertakan histori chat
  • Menyimpan respons model ke histori chat

Konfigurasi model

Metode chat() menerima sebagian besar opsi konfigurasi yang sama dengan generate(). Untuk meneruskan opsi konfigurasi ke model:

const chat = ai.chat({
  model: gemini15Pro,
  system:
    "You're a pirate first mate. Address the user as Captain and assist " +
    "them however you can.",
  config: {
    temperature: 1.3,
  },
});

Sesi chat stateful

Selain mempertahankan histori pesan sesi chat, Anda juga dapat mempertahankan objek JavaScript arbitrer. Dengan demikian, Anda dapat mengelola status dengan cara yang lebih terstruktur, lalu hanya mengandalkan informasi dalam histori pesan.

Untuk menyertakan status dalam sesi, Anda harus membuat instance sesi secara eksplisit:

interface MyState {
  userName: string;
}

const session = ai.createSession<MyState>({
  initialState: {
    userName: 'Pavel',
  },
});

Kemudian, Anda dapat memulai chat dalam sesi:

const chat = session.chat();

Untuk mengubah status sesi berdasarkan cara chat berlangsung, tentukan alat dan sertakan dengan permintaan Anda:

const changeUserName = ai.defineTool(
  {
    name: 'changeUserName',
    description: 'can be used to change user name',
    inputSchema: z.object({
      newUserName: z.string(),
    }),
  },
  async (input) => {
    await ai.currentSession<MyState>().updateState({
      userName: input.newUserName,
    });
    return 'changed username to ${input.newUserName}';
  }
);
const chat = session.chat({
  model: gemini15Pro,
  tools: [changeUserName],
});
await chat.send('change user name to Kevin');

Sesi multi-thread

Satu sesi dapat berisi beberapa rangkaian pesan chat. Setiap thread memiliki histori pesannya sendiri, tetapi memiliki satu status sesi yang sama.

const lawyerChat = session.chat('lawyerThread', {
  system: 'talk like a lawyer',
});
const pirateChat = session.chat('pirateThread', {
  system: 'talk like a pirate',
});

Persistensi sesi (EKSPERIMENTAL)

Saat Anda melakukan inisialisasi chat atau sesi baru, chat atau sesi tersebut dikonfigurasi secara default untuk menyimpan sesi hanya di memori. Hal ini memadai jika sesi hanya perlu dipertahankan selama durasi satu pemanggilan program Anda, seperti dalam contoh chatbot dari awal halaman ini. Namun, saat mengintegrasikan chat LLM ke dalam aplikasi, Anda biasanya akan men-deploy logika pembuatan konten sebagai endpoint API web stateless. Agar chat persisten berfungsi dalam penyiapan ini, Anda harus menerapkan semacam penyimpanan sesi yang dapat mempertahankan status di seluruh pemanggilan endpoint.

Untuk menambahkan persistensi ke sesi chat, Anda perlu mengimplementasikan antarmuka SessionStore Genkit. Berikut adalah contoh implementasi yang menyimpan status sesi ke setiap file JSON:

class JsonSessionStore<S = any> implements SessionStore<S> {
  async get(sessionId: string): Promise<SessionData<S> | undefined> {
    try {
      const s = await readFile(`${sessionId}.json`, { encoding: 'utf8' });
      const data = JSON.parse(s);
      return data;
    } catch {
      return undefined;
    }
  }

  async save(sessionId: string, sessionData: SessionData<S>): Promise<void> {
    const s = JSON.stringify(sessionData);
    await writeFile(`${sessionId}.json`, s, { encoding: 'utf8' });
  }
}

Implementasi ini mungkin tidak memadai untuk deployment praktis, tetapi menunjukkan bahwa implementasi penyimpanan sesi hanya perlu menyelesaikan dua tugas:

  • Mendapatkan objek sesi dari penyimpanan menggunakan ID sesi
  • Menyimpan objek sesi tertentu, yang diindeks berdasarkan ID sesi

Setelah mengimplementasikan antarmuka untuk backend penyimpanan, teruskan instance implementasi ke konstruktor sesi:

// To create a new session:
const session = ai.createSession({
  store: new JsonSessionStore(),
});

// Save session.id so you can restore the session the next time the
// user makes a request.
// If the user has a session ID saved, load the session instead of creating
// a new one:
const session = await ai.loadSession(sessionId, {
    store: new JsonSessionStore(),
});