Существуют различные категории информации, с которой разработчик, работающий с LLM, может работать одновременно:
- Входные данные: информация, которая имеет непосредственное отношение к реагированию LLM на конкретный вызов. Примером этого может служить текст, который необходимо резюмировать.
- Контекст генерации: информация, относящаяся к LLM, но не относящаяся к вызову. Примером этого является текущее время или имя пользователя.
- Контекст выполнения: информация, которая важна для кода, окружающего вызов LLM, но не для самого LLM. Примером этого является текущий токен аутентификации пользователя.
Genkit предоставляет согласованный объект context
, который может распространять контекст генерации и выполнения на протяжении всего процесса. Этот контекст доступен для всех действий, включая потоки , инструменты и подсказки .
Контекст автоматически распространяется на все действия, вызываемые в области выполнения: контекст, передаваемый в поток, становится доступным для подсказок, выполняемых внутри потока. Контекст, передаваемый методу generate()
, доступен инструментам, вызываемым в цикле генерации.
Почему важен контекст?
Рекомендуется предоставлять LLM минимальный объем информации, необходимый для выполнения задачи. Это важно по нескольким причинам:
- Чем меньше посторонней информации имеет LLM, тем больше вероятность, что он хорошо справится со своей задачей.
- Если LLM необходимо передать инструментам такую информацию, как идентификаторы пользователей или учетных записей, потенциально его можно обманом заставить утечь информацию.
Контекст предоставляет вам побочный канал информации, который может использоваться любым вашим кодом, но не обязательно отправляться в 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
во время его выполнения, будут наследовать переопределенный контекст.