Como transmitir informações pelo contexto

Há diferentes categorias de informações que um desenvolvedor que trabalha com um LLM pode processar simultaneamente:

  • Entrada:informações diretamente relevantes para orientar a resposta do LLM para uma chamada específica. Um exemplo disso é o texto que precisa ser resumido.
  • Contexto de geração:informações relevantes para o LLM, mas que não são específicas para a chamada. Um exemplo disso é a hora atual ou o nome de um usuário.
  • Contexto de execução:informações importantes para o código que envolve a chamada de LLM, mas não para o próprio LLM. Um exemplo disso é o token de autenticação atual de um usuário.

O Genkit fornece um objeto context consistente que pode propagar o contexto de geração e execução durante todo o processo. Esse contexto fica disponível para todas as ações, incluindo fluxos, ferramentas e comandos.

O contexto é propagado automaticamente para todas as ações chamadas no escopo da execução: o contexto transmitido para um fluxo é disponibilizado para as solicitações executadas no fluxo. O contexto transmitido ao método generate() está disponível para ferramentas chamadas no loop de geração.

Por que o contexto é importante?

Como prática recomendada, forneça ao LLM a quantidade mínima de informações necessárias para concluir uma tarefa. Isso é importante por vários motivos:

  • Quanto menos informações externas o LLM tiver, maior será a probabilidade de ele realizar bem a tarefa.
  • Se um LLM precisar transmitir informações como IDs de usuário ou de conta para ferramentas, ele poderá ser enganado para vazar informações.

O contexto oferece um canal secundário de informações que pode ser usado por qualquer um dos seus códigos, mas não precisa necessariamente ser enviado ao LLM. Por exemplo, ele pode permitir que você restrinja as consultas de ferramentas ao escopo disponível do usuário atual.

Estrutura de contexto

O contexto precisa ser um objeto, mas as propriedades são suas. Em algumas situações, o Genkit preenche o contexto automaticamente. Por exemplo, ao usar sessões persistentes, a propriedade state é adicionada automaticamente ao contexto.

Um dos usos mais comuns do contexto é armazenar informações sobre o usuário atual. Recomendamos adicionar o contexto de autenticação no seguinte formato:

{
  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
  }
}

O objeto de contexto pode armazenar qualquer informação que você precise saber em outro lugar no fluxo de execução.

Usar o contexto em uma ação

Para usar o contexto em uma ação, acesse o auxiliar de contexto fornecido automaticamente à definição da função:

Fluxo

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

Ferramenta

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

Arquivo de comando

Ao usar modelos do Dotprompt, o contexto fica disponível com o prefixo da variável @. Por exemplo, um objeto de contexto de {auth: {name: 'Michael'}} pode ser acessado no modelo de comando da seguinte maneira:

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

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

Oferecer contexto no momento da execução

Para fornecer contexto a uma ação, transmita o objeto de contexto como uma opção ao chamar a ação.

Fluxos

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

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

Geração

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

Comandos

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

Propagação e substituições de contexto

Por padrão, quando você fornece o contexto, ele é propagado automaticamente para todas as ações chamadas como resultado da chamada original. Se o fluxo chamar outros fluxos ou ferramentas de geração de chamadas, o mesmo contexto será fornecido.

Se você quiser substituir o contexto em uma ação, transmita um objeto de contexto diferente para substituir o atual:

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

Quando o contexto é substituído, ele se propaga da mesma maneira. Neste exemplo, todas as ações que otherFlow chamou durante a execução herdariam o contexto substituído.