通过上下文传递信息

使用 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 在执行期间调用的任何操作都会继承被替换的上下文。