永続的なチャット セッションを作成する

多くのユーザーは、chatbot を通じて初めて大規模言語モデルを操作することになります。LLM は会話のシミュレーション以外にも多くのことを行えますが、使い慣れた有用なインタラクション スタイルであることに変わりはありません。ユーザーがこの方法でモデルと直接やり取りしない場合でも、会話形式のプロンプトは、AI モデルによって生成される出力に影響を与える強力な方法です。

このようなインタラクションをサポートするため、Genkit は、チャットベースの LLM アプリケーションを簡単に構築できるように、一連のインターフェースと抽象化を提供します。

始める前に

このページを読む前に、AI モデルによるコンテンツの生成のページで説明されている内容を理解しておく必要があります。

このページのコードサンプルを実行する場合は、まずスタートガイドの手順を完了してください。以下の例では、Genkit がプロジェクトの依存関係としてすでにインストールされていることを前提としています。

チャット セッションの基本

以下に、コンソール ベースの最小限の chatbot アプリケーションを示します。

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);
  }
})();

このプログラムでのチャット セッションは、次の例のようになります。

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?

この簡単なやり取りからわかるように、チャット セッションにメッセージを送信すると、モデルはこれまでのセッシションをレスポンスで使用できます。これは、Genkit がバックグラウンドで次のことを行っているためです。

  • ストレージからチャットの履歴を取得します(永続性とストレージについては後述)。
  • generate() と同様にモデルにリクエストを送信しますが、チャット履歴が自動的に含まれます。
  • モデルのレスポンスをチャットの履歴に保存します。

モデル設定

chat() メソッドは、generate() と同じ構成オプションのほとんどを受け入れます。構成オプションをモデルに渡すには:

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,
  },
});

ステートフル チャット セッション

チャット セッションのメッセージ履歴を保持するだけでなく、任意の JavaScript オブジェクトを保持することもできます。これにより、メッセージ履歴の情報のみに依存するのではなく、より構造化された方法で状態を管理できます。

セッションに状態を含めるには、セッションを明示的にインスタンス化する必要があります。

interface MyState {
  userName: string;
}

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

セッション内でチャットを開始できます。

const chat = session.chat();

チャットの進行状況に応じてセッション状態を変更するには、ツールを定義してリクエストに含めます。

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');

マルチスレッド セッション

1 つのセッションに複数のチャット スレッドを含めることができます。各スレッドには独自のメッセージ履歴がありますが、単一のセッション状態を共有します。

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

セッションの永続性(試験運用版)

新しいチャットまたはセッションを初期化すると、デフォルトではセッションがメモリにのみ保存されるように構成されます。これは、このページの冒頭のサンプル チャットボットのように、プログラムの 1 回の呼び出しの期間のみセッションを保持する必要がある場合に適しています。ただし、LLM チャットをアプリケーションに統合する場合は、通常、コンテンツ生成ロジックをステートレスなウェブ API エンドポイントとしてデプロイします。この設定で永続チャットを機能させるには、エンドポイントの呼び出し間で状態を保持できるなんらかのセッション ストレージを実装する必要があります。

チャット セッションに永続性を追加するには、Genkit の SessionStore インターフェースを実装する必要があります。セッション状態を個別の 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' });
  }
}

この実装は実用的なデプロイには適していない可能性がありますが、セッション ストレージの実装では次の 2 つのタスクのみを行う必要があることを示しています。

  • セッション ID を使用してストレージからセッション オブジェクトを取得する
  • 指定されたセッション オブジェクトをセッション ID でインデックスに登録して保存する

ストレージ バックエンドのインターフェースを実装したら、実装のインスタンスをセッション コンストラクタに渡します。

// 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(),
});