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.