আপনার অ্যাপের AI বৈশিষ্ট্যগুলির মূল হল জেনারেটিভ মডেলের অনুরোধ, কিন্তু এটি বিরল যে আপনি কেবল ব্যবহারকারীর ইনপুট নিতে পারেন, এটি মডেলে পাস করতে পারেন এবং ব্যবহারকারীর কাছে মডেল আউটপুটটি প্রদর্শন করতে পারেন। সাধারণত, মডেল কলের সাথে অবশ্যই প্রি- এবং পোস্ট-প্রসেসিং ধাপ রয়েছে। যেমন:
- মডেল কলের সাথে পাঠানোর জন্য প্রাসঙ্গিক তথ্য পুনরুদ্ধার করা হচ্ছে
- ব্যবহারকারীর বর্তমান সেশনের ইতিহাস পুনরুদ্ধার করা, উদাহরণস্বরূপ একটি চ্যাট অ্যাপে
- একটি মডেল ব্যবহার করে ব্যবহারকারীর ইনপুটকে এমনভাবে পুনরায় ফর্ম্যাট করা যা অন্য মডেলে পাস করার জন্য উপযুক্ত
- ব্যবহারকারীর কাছে উপস্থাপন করার আগে একটি মডেলের আউটপুটের "নিরাপত্তা" মূল্যায়ন করা
- বেশ কয়েকটি মডেলের আউটপুট একত্রিত করা
এআই-সম্পর্কিত যেকোনো কাজ সফল হওয়ার জন্য এই কর্মপ্রবাহের প্রতিটি ধাপে একসঙ্গে কাজ করতে হবে।
জেনকিটে, আপনি একটি প্রবাহ নামক একটি নির্মাণ ব্যবহার করে এই শক্তভাবে-সংযুক্ত যুক্তি উপস্থাপন করেন। ফ্লোগুলি সাধারণ টাইপস্ক্রিপ্ট কোড ব্যবহার করে ফাংশনের মতোই লেখা হয়, তবে তারা এআই বৈশিষ্ট্যগুলির বিকাশকে সহজ করার উদ্দেশ্যে অতিরিক্ত ক্ষমতা যুক্ত করে:
- প্রকার নিরাপত্তা : Zod ব্যবহার করে সংজ্ঞায়িত ইনপুট এবং আউটপুট স্কিমা, যা স্ট্যাটিক এবং রানটাইম টাইপ চেকিং উভয়ই প্রদান করে
- বিকাশকারী UI এর সাথে একীকরণ : বিকাশকারী UI ব্যবহার করে আপনার অ্যাপ্লিকেশন কোড থেকে স্বাধীনভাবে ডিবাগ প্রবাহিত হয়। বিকাশকারী UI-তে, আপনি প্রবাহ চালাতে পারেন এবং প্রবাহের প্রতিটি ধাপের জন্য ট্রেস দেখতে পারেন।
- সরলীকৃত স্থাপনা : ফায়ারবেসের জন্য ক্লাউড ফাংশন বা ওয়েব অ্যাপ হোস্ট করতে পারে এমন কোনো প্ল্যাটফর্ম ব্যবহার করে সরাসরি ওয়েব API এন্ডপয়েন্ট হিসেবে প্রবাহ স্থাপন করুন।
অন্যান্য ফ্রেমওয়ার্কের অনুরূপ বৈশিষ্ট্যগুলির বিপরীতে, জেনকিটের প্রবাহগুলি হালকা এবং বাধাহীন, এবং আপনার অ্যাপটিকে কোনও নির্দিষ্ট বিমূর্ততার সাথে সামঞ্জস্য করতে বাধ্য করে না। প্রবাহের সমস্ত যুক্তি স্ট্যান্ডার্ড টাইপস্ক্রিপ্টে লেখা হয় এবং একটি প্রবাহের ভিতরের কোডের প্রবাহ-সচেতন হওয়ার প্রয়োজন নেই।
সংজ্ঞায়িত এবং কলিং প্রবাহ
এর সহজতম আকারে, একটি প্রবাহ কেবল একটি ফাংশনকে মোড়ানো হয়। নিম্নলিখিত উদাহরণটি একটি ফাংশনকে মোড়ানো হয় যা generate()
কল করে:
export const menuSuggestionFlow = ai.defineFlow(
{
name: 'menuSuggestionFlow',
},
async (restaurantTheme) => {
const { text } = await ai.generate({
model: gemini15Flash,
prompt: `Invent a menu item for a ${restaurantTheme} themed restaurant.`,
});
return text;
}
);
শুধু আপনার generate()
কলগুলিকে এইভাবে মোড়ানোর মাধ্যমে, আপনি কিছু কার্যকারিতা যোগ করেন: এটি করার ফলে আপনি জেনকিট সিএলআই এবং বিকাশকারী UI থেকে প্রবাহ চালাতে পারবেন এবং স্থাপনা এবং পর্যবেক্ষণযোগ্যতা সহ (পরবর্তী বিভাগগুলি) সহ জেনকিটের বেশ কয়েকটি বৈশিষ্ট্যের জন্য এটি প্রয়োজনীয়। এই বিষয়গুলি নিয়ে আলোচনা করুন)।
ইনপুট এবং আউটপুট স্কিমা
Genkit ফ্লোতে সরাসরি একটি মডেল API কল করার সবচেয়ে গুরুত্বপূর্ণ সুবিধাগুলির মধ্যে একটি হল ইনপুট এবং আউটপুট উভয়ের ধরনের নিরাপত্তা। প্রবাহ সংজ্ঞায়িত করার সময়, আপনি Zod ব্যবহার করে তাদের জন্য স্কিমাগুলিকে সংজ্ঞায়িত করতে পারেন, যেমন আপনি একটি generate()
কলের আউটপুট স্কিমা সংজ্ঞায়িত করেন; যাইহোক, generate()
এর বিপরীতে, আপনি একটি ইনপুট স্কিমাও নির্দিষ্ট করতে পারেন।
এখানে শেষ উদাহরণের একটি পরিমার্জন রয়েছে, যা একটি প্রবাহকে সংজ্ঞায়িত করে যা একটি স্ট্রিংকে ইনপুট হিসাবে নেয় এবং একটি বস্তুকে আউটপুট করে:
const MenuItemSchema = z.object({
dishname: z.string(),
description: z.string(),
});
export const menuSuggestionFlowWithSchema = ai.defineFlow(
{
name: 'menuSuggestionFlow',
inputSchema: z.string(),
outputSchema: MenuItemSchema,
},
async (restaurantTheme) => {
const { output } = await ai.generate({
model: gemini15Flash,
prompt: `Invent a menu item for a ${restaurantTheme} themed restaurant.`,
output: { schema: MenuItemSchema },
});
if (output == null) {
throw new Error("Response doesn't satisfy schema.");
}
return output;
}
);
মনে রাখবেন যে একটি প্রবাহের স্কিমা অগত্যা প্রবাহের মধ্যে generate()
কলের স্কিমার সাথে লাইন আপ করতে হবে না (আসলে, একটি ফ্লোতে generate()
কলও থাকতে পারে না)। এখানে উদাহরণের একটি ভিন্নতা রয়েছে যা একটি স্কিমাকে generate()
করতে পাস করে, কিন্তু একটি সাধারণ স্ট্রিং ফর্ম্যাট করতে কাঠামোগত আউটপুট ব্যবহার করে, যা প্রবাহটি ফেরত দেয়।
export const menuSuggestionFlowMarkdown = ai.defineFlow(
{
name: 'menuSuggestionFlow',
inputSchema: z.string(),
outputSchema: z.string(),
},
async (restaurantTheme) => {
const { output } = await ai.generate({
model: gemini15Flash,
prompt: `Invent a menu item for a ${restaurantTheme} themed restaurant.`,
output: { schema: MenuItemSchema },
});
if (output == null) {
throw new Error("Response doesn't satisfy schema.");
}
return `**${output.dishname}**: ${output.description}`;
}
);
কলিং প্রবাহ
একবার আপনি একটি প্রবাহ সংজ্ঞায়িত করলে, আপনি এটিকে আপনার Node.js কোড থেকে কল করতে পারেন:
const { text } = await menuSuggestionFlow('bistro');
প্রবাহের যুক্তি অবশ্যই ইনপুট স্কিমার সাথে সঙ্গতিপূর্ণ হবে, যদি আপনি একটি সংজ্ঞায়িত করেন।
আপনি যদি একটি আউটপুট স্কিমা সংজ্ঞায়িত করেন তবে প্রবাহ প্রতিক্রিয়া এটির সাথে সামঞ্জস্যপূর্ণ হবে। উদাহরণস্বরূপ, যদি আপনি MenuItemSchema
তে আউটপুট স্কিমা সেট করেন, তাহলে ফ্লো আউটপুটে এর বৈশিষ্ট্য থাকবে:
const { dishname, description } =
await menuSuggestionFlowWithSchema('bistro');
স্ট্রিমিং প্রবাহ
ফ্লোস generate()
এর স্ট্রিমিং ইন্টারফেসের মতো একটি ইন্টারফেস ব্যবহার করে স্ট্রিমিং সমর্থন করে। আপনার প্রবাহ যখন প্রচুর পরিমাণে আউটপুট জেনারেট করে তখন স্ট্রিমিং উপযোগী হয়, কারণ আপনি ব্যবহারকারীর কাছে আউটপুটটি উত্পন্ন হওয়ার সাথে সাথে উপস্থাপন করতে পারেন, যা আপনার অ্যাপের অনুভূত প্রতিক্রিয়াশীলতাকে উন্নত করে। একটি পরিচিত উদাহরণ হিসাবে, চ্যাট-ভিত্তিক LLM ইন্টারফেসগুলি প্রায়শই ব্যবহারকারীর কাছে তাদের প্রতিক্রিয়াগুলি তৈরি করার সাথে সাথে স্ট্রিম করে।
এখানে একটি প্রবাহের একটি উদাহরণ যা স্ট্রিমিং সমর্থন করে:
export const menuSuggestionStreamingFlow = ai.defineStreamingFlow(
{
name: 'menuSuggestionFlow',
inputSchema: z.string(),
streamSchema: z.string(),
outputSchema: z.object({ theme: z.string(), menuItem: z.string() }),
},
async (restaurantTheme, streamingCallback) => {
const response = await ai.generateStream({
model: gemini15Flash,
prompt: `Invent a menu item for a ${restaurantTheme} themed restaurant.`,
});
if (streamingCallback) {
for await (const chunk of response.stream) {
// Here, you could process the chunk in some way before sending it to
// the output stream via streamingCallback(). In this example, we output
// the text of the chunk, unmodified.
streamingCallback(chunk.text);
}
}
return {
theme: restaurantTheme,
menuItem: (await response.response).text,
};
}
);
-
streamSchema
বিকল্পটি আপনার ফ্লো স্ট্রীমের মানগুলির ধরন নির্দিষ্ট করে৷ এটি অগত্যাoutputSchema
এর মতো একই ধরণের হতে হবে না, যা প্রবাহের সম্পূর্ণ আউটপুটের প্রকার। -
streamingCallback
হল একটি কলব্যাক ফাংশন যাstreamSchema
দ্বারা নির্দিষ্ট ধরনের একটি একক প্যারামিটার নেয়। যখনই আপনার প্রবাহের মধ্যে ডেটা উপলব্ধ হয়, এই ফাংশনটি কল করে আউটপুট স্ট্রীমে ডেটা পাঠান। মনে রাখবেন যেstreamingCallback
শুধুমাত্র তখনই সংজ্ঞায়িত করা হয় যখন আপনার ফ্লো-এর কলার স্ট্রিমিং আউটপুটের জন্য অনুরোধ করে, তাই আপনাকে এটি কল করার আগে এটি সংজ্ঞায়িত করা আছে কিনা তা পরীক্ষা করতে হবে।
উপরের উদাহরণে, প্রবাহ দ্বারা প্রবাহিত মানগুলি প্রবাহের ভিতরে generate()
কল দ্বারা প্রবাহিত মানগুলির সাথে সরাসরি মিলিত হয়। যদিও এটি প্রায়শই হয়, এটি হওয়ার দরকার নেই: আপনি যতবার আপনার প্রবাহের জন্য উপযোগী ততবার কলব্যাক ব্যবহার করে স্ট্রীমে মানগুলি আউটপুট করতে পারেন।
কলিং স্ট্রিমিং প্রবাহ
স্ট্রিমিং প্রবাহও কলযোগ্য, কিন্তু তারা অবিলম্বে একটি প্রতিশ্রুতির পরিবর্তে একটি প্রতিক্রিয়া বস্তু ফিরিয়ে দেয়:
const response = menuSuggestionStreamingFlow('Danube');
রেসপন্স অবজেক্টের একটি স্ট্রীম প্রপার্টি রয়েছে, যা আপনি প্রবাহের স্ট্রিমিং আউটপুট তৈরি করার সাথে সাথে পুনরাবৃত্তি করতে ব্যবহার করতে পারেন:
for await (const chunk of response.stream) {
console.log('chunk', chunk);
}
আপনি প্রবাহের সম্পূর্ণ আউটপুটও পেতে পারেন, যেমন আপনি একটি অ-স্ট্রিমিং প্রবাহের সাথে পারেন:
const output = await response.output;
মনে রাখবেন যে একটি প্রবাহের স্ট্রিমিং আউটপুট সম্পূর্ণ আউটপুটের মতো একই ধরনের নাও হতে পারে; স্ট্রিমিং আউটপুট streamSchema
সাথে সামঞ্জস্যপূর্ণ, যেখানে সম্পূর্ণ আউটপুট outputSchema
সাথে সামঞ্জস্যপূর্ণ।
কমান্ড লাইন থেকে চলমান প্রবাহ
আপনি Genkit CLI টুল ব্যবহার করে কমান্ড লাইন থেকে প্রবাহ চালাতে পারেন:
genkit flow:run menuSuggestionFlow '"French"'
স্ট্রিমিং প্রবাহের জন্য, আপনি -s
পতাকা যোগ করে কনসোলে স্ট্রিমিং আউটপুট মুদ্রণ করতে পারেন:
genkit flow:run menuSuggestionFlow '"French"' -s
কমান্ড লাইন থেকে একটি প্রবাহ চালানো একটি ফ্লো পরীক্ষা করার জন্য, বা অ্যাডহক ভিত্তিতে প্রয়োজনীয় কাজগুলি সঞ্চালন করার জন্য প্রবাহ চালানোর জন্য দরকারী - উদাহরণস্বরূপ, একটি প্রবাহ চালানোর জন্য যা আপনার ভেক্টর ডাটাবেসে একটি নথি প্রবেশ করে৷
ডিবাগিং প্রবাহ
একটি প্রবাহের মধ্যে AI লজিককে এনক্যাপসুলেট করার সুবিধাগুলির মধ্যে একটি হল যে আপনি Genkit বিকাশকারী UI ব্যবহার করে আপনার অ্যাপ থেকে স্বাধীনভাবে ফ্লো পরীক্ষা এবং ডিবাগ করতে পারেন।
বিকাশকারী UI শুরু করতে, আপনার প্রকল্প ডিরেক্টরি থেকে নিম্নলিখিত কমান্ডগুলি চালান:
genkit start -- tsx --watch src/your-code.ts
বিকাশকারী UI এর রান ট্যাব থেকে, আপনি আপনার প্রকল্পে সংজ্ঞায়িত যে কোনও প্রবাহ চালাতে পারেন:
আপনি একটি ফ্লো চালানোর পরে, আপনি ভিউ ট্রেস ক্লিক করে বা পরিদর্শন ট্যাবে দেখে ফ্লো ইনভোকেশনের একটি ট্রেস পরিদর্শন করতে পারেন।
ট্রেস ভিউয়ারে, আপনি সম্পূর্ণ প্রবাহের সঞ্চালনের বিবরণ, সেইসাথে প্রবাহের মধ্যে প্রতিটি পৃথক পদক্ষেপের বিবরণ দেখতে পারেন। উদাহরণস্বরূপ, নিম্নলিখিত প্রবাহটি বিবেচনা করুন, যাতে বেশ কয়েকটি প্রজন্মের অনুরোধ রয়েছে:
const PrixFixeMenuSchema = z.object({
starter: z.string(),
soup: z.string(),
main: z.string(),
dessert: z.string(),
});
export const complexMenuSuggestionFlow = ai.defineFlow(
{
name: 'complexMenuSuggestionFlow',
inputSchema: z.string(),
outputSchema: PrixFixeMenuSchema,
},
async (theme: string): Promise<z.infer<typeof PrixFixeMenuSchema>> => {
const chat = ai.chat({ model: gemini15Flash });
await chat.send('What makes a good prix fixe menu?');
await chat.send(
'What are some ingredients, seasonings, and cooking techniques that ' +
`would work for a ${theme} themed menu?`
);
const { output } = await chat.send({
prompt:
`Based on our discussion, invent a prix fixe menu for a ${theme} ` +
'themed restaurant.',
output: {
schema: PrixFixeMenuSchema,
},
});
if (!output) {
throw new Error('No data generated.');
}
return output;
}
);
আপনি যখন এই প্রবাহটি চালান, তখন ট্রেস ভিউয়ার আপনাকে প্রতিটি প্রজন্মের অনুরোধের আউটপুট সহ বিস্তারিত দেখায়:
প্রবাহ পদক্ষেপ
শেষ উদাহরণে, আপনি দেখেছেন যে প্রতিটি generate()
কল ট্রেস ভিউয়ারে একটি পৃথক পদক্ষেপ হিসাবে দেখানো হয়েছে। জেনকিটের প্রতিটি মৌলিক ক্রিয়া একটি প্রবাহের পৃথক পদক্ষেপ হিসাবে প্রদর্শিত হয়:
-
generate()
-
Chat.send()
-
embed()
-
index()
-
retrieve()
আপনি যদি আপনার ট্রেসে উপরের কোডগুলি ব্যতীত অন্য কোড অন্তর্ভুক্ত করতে চান তবে আপনি run()
কলে কোডটি মোড়ানোর মাধ্যমে তা করতে পারেন। আপনি এটি করতে পারেন তৃতীয় পক্ষের লাইব্রেরিতে কল করার জন্য যা জেনকিট-সচেতন নয়, বা কোডের কোনো সমালোচনামূলক বিভাগের জন্য।
উদাহরণস্বরূপ, এখানে দুটি ধাপ সহ একটি প্রবাহ রয়েছে: প্রথম ধাপটি কিছু অনির্দিষ্ট পদ্ধতি ব্যবহার করে একটি মেনু পুনরুদ্ধার করে এবং দ্বিতীয় ধাপে একটি generate()
কলের প্রসঙ্গ হিসাবে মেনু অন্তর্ভুক্ত করে।
export const menuQuestionFlow = ai.defineFlow(
{
name: 'menuQuestionFlow',
inputSchema: z.string(),
outputSchema: z.string(),
},
async (input: string): Promise<string> => {
const menu = await run('retrieve-daily-menu', async (): Promise<string> => {
// Retrieve today's menu. (This could be a database access or simply
// fetching the menu from your website.)
// ...
return menu;
});
const { text } = await ai.generate({
model: gemini15Flash,
system: "Help the user answer questions about today's menu.",
prompt: input,
docs: [{ content: [{ text: menu }] }],
});
return text;
}
);
যেহেতু পুনরুদ্ধারের পদক্ষেপটি run()
কলে মোড়ানো হয়েছে, এটি ট্রেস ভিউয়ারের একটি ধাপ হিসাবে অন্তর্ভুক্ত করা হয়েছে:
প্রবাহ স্থাপন
আপনি আপনার অ্যাপ ক্লায়েন্টদের থেকে কল করার জন্য প্রস্তুত, ওয়েব API এন্ডপয়েন্ট হিসাবে সরাসরি আপনার প্রবাহ স্থাপন করতে পারেন। স্থাপনার বিষয়ে অন্যান্য কয়েকটি পৃষ্ঠায় বিস্তারিত আলোচনা করা হয়েছে, তবে এই বিভাগটি আপনার স্থাপনার বিকল্পগুলির সংক্ষিপ্ত বিবরণ দেয়।
ফায়ারবেসের জন্য ক্লাউড ফাংশন
ফায়ারবেসের জন্য ক্লাউড ফাংশনগুলির সাথে প্রবাহ স্থাপন করতে, firebase
প্লাগইন ব্যবহার করুন। আপনার ফ্লো সংজ্ঞায়, defineFlow
onFlow
দিয়ে প্রতিস্থাপন করুন এবং একটি authPolicy
অন্তর্ভুক্ত করুন।
import { firebaseAuth } from '@genkit-ai/firebase/auth';
import { onFlow } from '@genkit-ai/firebase/functions';
export const menuSuggestion = onFlow(
ai,
{
name: 'menuSuggestionFlow',
authPolicy: firebaseAuth((user) => {
if (!user.email_verified) {
throw new Error('Verified email required to run flow');
}
}),
},
async (restaurantTheme) => {
// ...
}
);
আরও তথ্যের জন্য, নিম্নলিখিত পৃষ্ঠাগুলি দেখুন:
Express.js
যেকোন Node.js হোস্টিং প্ল্যাটফর্ম ব্যবহার করে ফ্লো স্থাপন করতে, যেমন ক্লাউড রান, defineFlow()
ব্যবহার করে আপনার ফ্লো সংজ্ঞায়িত করুন এবং তারপর startFlowServer()
কল করুন :
export const menuSuggestionFlow = ai.defineFlow(
{
name: 'menuSuggestionFlow',
},
async (restaurantTheme) => {
// ...
}
);
ai.startFlowServer({
flows: [menuSuggestionFlow],
});
ডিফল্টরূপে, startFlowServer
আপনার কোডবেসে সংজ্ঞায়িত সমস্ত ফ্লোকে HTTP এন্ডপয়েন্ট হিসেবে পরিবেশন করবে (উদাহরণস্বরূপ, http://localhost:3400/menuSuggestionFlow
)। আপনি নিম্নরূপ একটি POST অনুরোধ সহ একটি প্রবাহ কল করতে পারেন:
curl -X POST "http://localhost:3400/menuSuggestionFlow" \
-H "Content-Type: application/json" -d '{"data": "banana"}'
প্রয়োজন হলে, আপনি প্রবাহের একটি নির্দিষ্ট তালিকা পরিবেশন করতে ফ্লো সার্ভার কাস্টমাইজ করতে পারেন, যেমনটি নীচে দেখানো হয়েছে। আপনি একটি কাস্টম পোর্টও নির্দিষ্ট করতে পারেন (সেট থাকলে এটি PORT পরিবেশ ভেরিয়েবল ব্যবহার করবে) বা CORS সেটিংস নির্দিষ্ট করতে পারেন।
export const flowA = ai.defineFlow({ name: 'flowA' }, async (subject) => {
// ...
});
export const flowB = ai.defineFlow({ name: 'flowB' }, async (subject) => {
// ...
});
ai.startFlowServer({
flows: [flowB],
port: 4567,
cors: {
origin: '*',
},
});
নির্দিষ্ট প্ল্যাটফর্মে স্থাপনের তথ্যের জন্য, যে কোনো Node.js প্ল্যাটফর্মে Deploy with Cloud Run এবং Deploy flows দেখুন।