コンテキストを介した情報の受け渡し

LLM を扱うデベロッパーが同時に処理する情報には、次のカテゴリがあります。

  • 入力: 特定の呼び出しに対する LLM のレスポンスを誘導するために直接関連する情報。たとえば、要約する必要があるテキストなどです。
  • 生成コンテキスト: LLM に関連するが、呼び出しに固有ではない情報。たとえば、現在の時刻やユーザーの名前などです。
  • 実行コンテキスト: LLM 呼び出しの周囲のコードにとって重要だが、LLM 自体には重要ではない情報。たとえば、ユーザーの現在の認証トークンなどです。

Genkit は、生成と実行のコンテキストをプロセス全体に伝播できる一貫した context オブジェクトを提供します。このコンテキストは、フローツールプロンプトなど、すべてのアクションで使用できます。

コンテキストは、実行スコープ内で呼び出されるすべてのアクションに自動的に伝播されます。フローに渡されたコンテキストは、フロー内で実行されるプロンプトで使用できます。generate() メソッドに渡されたコンテキストは、生成ループ内で呼び出されるツールで使用できます。

コンテキストが重要である理由

ベスト プラクティスとして、タスクの完了に必要な最小限の情報のみを LLM に提供します。これは、次の理由で重要です。

  • LLM に余分な情報が少ないほど、タスクを適切に実行できる可能性が高くなります。
  • LLM がユーザー ID やアカウント ID などの情報をツールに渡す必要がある場合、情報漏洩につながる可能性があります。

コンテキストは、任意のコードで使用できる情報のサイドチャネルを提供しますが、LLM に送信する必要はありません。たとえば、ツールクエリを現在のユーザーが使用可能なスコープに制限できます。

コンテキストの構造

コンテキストはオブジェクトである必要がありますが、そのプロパティは任意で設定できます。状況によっては、Genkit がコンテキストを自動的に入力します。たとえば、永続セッションを使用すると、state プロパティがコンテキストに自動的に追加されます。

コンテキストの最も一般的な用途の一つは、現在のユーザーに関する情報を保存することです。認証コンテキストは、次の形式で追加することをおすすめします。

{
  auth: {
    uid: "...", // the user's unique identifier
    token: {...}, // the decoded claims of a user's id token
    rawToken: "...", // the user's raw encoded id token
    // ...any other fields
  }
}

コンテキスト オブジェクトには、実行フローの他の場所で必要になる可能性のある情報を保存できます。

アクションでコンテキストを使用する

アクション内でコンテキストを使用するには、関数定義に自動的に提供されるコンテキスト ヘルパーにアクセスします。

フロー

const summarizeHistory = ai.defineFlow({
  name: 'summarizeMessages',
  inputSchema: z.object({friendUid: z.string()}),
  outputSchema: z.string();
}, async ({friendUid}, {context}) => {
  if (!context.auth?.uid) throw new Error("Must supply auth context.");
  const messages = await listMessagesBetween(friendUid, context.auth.uid);
  const {text} = await ai.generate({
    prompt:
      `Summarize the content of these messages: ${JSON.stringify(messages)}`,
  });
  return text;
});

ツール

const searchNotes = ai.defineTool({
  name: 'searchNotes',
  description: "search the current user's notes for info",
  inputSchema: z.object({query: z.string()}),
  outputSchmea: z.array(NoteSchema);
}, async ({query}, {context}) => {
  if (!context.auth?.uid) throw new Error("Must be called by a signed-in user.");
  return searchUserNotes(context.auth.uid, query);
});

プロンプト ファイル

Dotprompt テンプレートを使用する場合、コンテキストは @ 変数接頭辞で使用できます。たとえば、{auth: {name: 'Michael'}} のコンテキスト オブジェクトには、次のようにプロンプト テンプレートでアクセスできます。

---
input:
  schema:
    pirateStyle?: boolean
---

{{#if pirateStyle}}
Avast, {{@auth.name}}, how be ye today?
{{else}}
Hello, {{@auth.name}}, how are you today?
{{/if}}

実行時にコンテキストを提供する

アクションにコンテキストを指定するには、アクションを呼び出すときにコンテキスト オブジェクトをオプションとして渡します。

フロー

const summarizeHistory = ai.defineFlow(/* ... */);

const summary = await summarizeHistory(friend.uid, {context: {auth: currentUser}});

生成

const {text} = await ai.generate({
  prompt: "Find references to ocelots in my notes.",
  // the context will propagate to tool calls
  tools: [searchNotes],
  context: {auth: currentUser},
});

プロンプト

const helloPrompt = ai.prompt('sayHello');
helloPrompt({pirateStyle: true}, {context: {auth: currentUser}});

コンテキストの伝播とオーバーライド

デフォルトでは、コンテキストを指定すると、元の呼び出しの結果として呼び出されるすべてのアクションに自動的に伝播されます。フローが他のフローを呼び出す場合や、生成ツールを呼び出す場合、同じコンテキストが提供されます。

アクション内でコンテキストをオーバーライドする場合は、別のコンテキスト オブジェクトを渡して既存のコンテキストを置き換えることができます。

const otherFlow = ai.defineFlow(/* ... */);

const myFlow = ai.defineFlow({
  // ...
}, (input, {context}) => {
  // override the existing context completely
  otherFlow({/*...*/}, {context: {newContext: true}});
  // or selectively override
  otherFlow({/*...*/}, {context: {...context, updatedContext: true}});
}); 

コンテキストが置き換えられると、同じ方法で伝播されます。この例では、otherFlow が実行中に呼び出したアクションはすべて、オーバーライドされたコンテキストを継承します。