Cómo pasar información a través del contexto

Existen diferentes categorías de información que un desarrollador que trabaja con un LLM puede controlar de forma simultánea:

  • Entrada: Es la información que es directamente relevante para guiar la respuesta del LLM para una llamada en particular. Un ejemplo de esto es el texto que se debe resumir.
  • Contexto de generación: Es la información que es relevante para el LLM, pero que no es específica de la llamada. Un ejemplo de esto es la hora actual o el nombre de un usuario.
  • Contexto de ejecución: Es la información que es importante para el código que rodea la llamada al LLM, pero no para el LLM en sí. Un ejemplo de esto es el token de autenticación actual de un usuario.

Genkit proporciona un objeto context coherente que puede propagar el contexto de generación y ejecución durante todo el proceso. Este contexto está disponible para todas las acciones, incluidos los flujos, las herramientas y los mensajes.

El contexto se propaga automáticamente a todas las acciones a las que se llama dentro del alcance de la ejecución: el contexto que se pasa a un flujo está disponible para las instrucciones que se ejecutan dentro del flujo. El contexto que se pasa al método generate() está disponible para las herramientas que se llaman dentro del bucle de generación.

¿Por qué es importante el contexto?

Como práctica recomendada, debes proporcionarle al LLM la cantidad mínima de información que necesita para completar una tarea. Esto es importante por varios motivos:

  • Cuanto menos información irrelevante tenga el LLM, es más probable que realice bien su tarea.
  • Si un LLM necesita pasar información, como IDs de usuario o de cuenta, a las herramientas, es posible que se engañe para que filtre información.

El contexto te brinda un canal lateral de información que puede usar cualquiera de tus códigos, pero que no necesariamente se debe enviar al LLM. Por ejemplo, puede permitirte restringir las consultas de la herramienta al alcance disponible del usuario actual.

Estructura del contexto

El contexto debe ser un objeto, pero tú decides cuáles son sus propiedades. En algunas situaciones, Genkit propaga automáticamente el contexto. Por ejemplo, cuando usas sesiones persistentes, la propiedad state se agrega automáticamente al contexto.

Uno de los usos más comunes del contexto es almacenar información sobre el usuario actual. Te recomendamos que agregues el contexto de autenticación en el siguiente 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
  }
}

El objeto de contexto puede almacenar cualquier información que necesites saber en otro lugar del flujo de ejecución.

Cómo usar el contexto en una acción

Para usar el contexto dentro de una acción, puedes acceder al asistente de contexto que se proporciona automáticamente a la definición de tu función:

Flujo

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

Herramienta

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

Archivo de la instrucción

Cuando se usan plantillas de Dotprompt, el contexto está disponible con el prefijo de variable @. Por ejemplo, se podría acceder a un objeto de contexto de {auth: {name: 'Michael'}} en la plantilla de instrucción de la siguiente manera:

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

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

Proporciona contexto durante el tiempo de ejecución

Para proporcionar contexto a una acción, pasas el objeto de contexto como una opción cuando llamas a la acción.

Flows

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

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

Generación

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

Instrucciones

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

Anulaciones y propagación de contexto

De forma predeterminada, cuando proporcionas contexto, este se propaga automáticamente a todas las acciones a las que se llama como resultado de tu llamada original. Si tu flujo llama a otros flujos o si tu generación llama a herramientas, se proporciona el mismo contexto.

Si deseas anular el contexto dentro de una acción, puedes pasar un objeto de contexto diferente para reemplazar el existente:

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

Cuando se reemplaza el contexto, se propaga de la misma manera. En este ejemplo, cualquier acción a la que otherFlow llamó durante su ejecución heredaría el contexto anulado.