एलएलएम के साथ काम करने वाला डेवलपर, जानकारी की अलग-अलग कैटगरी को एक साथ मैनेज कर सकता है:
- इनपुट: किसी कॉल के लिए एलएलएम के जवाब को दिशा देने के लिए, सीधे तौर पर काम की जानकारी. इसका एक उदाहरण वह टेक्स्ट है जिसकी खास जानकारी चाहिए.
- जनरेशन कॉन्टेक्स्ट: ऐसी जानकारी जो एलएलएम के लिए काम की है, लेकिन कॉल के लिए खास नहीं है. इसका उदाहरण, मौजूदा समय या उपयोगकर्ता का नाम है.
- एक्सीक्यूशन कॉन्टेक्स्ट: यह ऐसी जानकारी होती है जो एलएलएम कॉल के आस-पास मौजूद कोड के लिए ज़रूरी होती है, लेकिन एलएलएम के लिए नहीं. इसका एक उदाहरण, उपयोगकर्ता का मौजूदा पुष्टि करने वाला टोकन है.
Genkit एक ऐसा context
ऑब्जेक्ट उपलब्ध कराता है जो पूरी प्रोसेस के दौरान जनरेशन और टास्क को लागू करने के कॉन्टेक्स्ट को प्रोपैगेट कर सकता है. यह कॉन्टेक्स्ट, सभी कार्रवाइयों के लिए उपलब्ध कराया जाता है. इनमें फ़्लो, टूल, और प्रॉम्प्ट शामिल हैं.
कॉन्टेक्स्ट, प्रोसेस करने के दायरे में आने वाली सभी कार्रवाइयों में अपने-आप भेज दिया जाता है: किसी फ़्लो में भेजा गया कॉन्टेक्स्ट, फ़्लो में लागू किए गए प्रॉम्प्ट के लिए उपलब्ध कराया जाता है. generate()
तरीके में पास किया गया कॉन्टेक्स्ट, जनरेशन लूप में कॉल किए गए टूल के लिए उपलब्ध होता है.
संदर्भ ज़रूरी क्यों है?
सबसे सही तरीके के तौर पर, आपको 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
के एक्सीक्यूशन के दौरान की गई सभी कार्रवाइयों को, बदले गए कॉन्टेक्स्ट को इनहेरिट करना होगा.